什么是Java虚拟机
此处涉及到两个概念:
- Java虚拟机,相当于我们定义的Java类
- Java虚拟机实例,相当于new一个Java类
注意:Java虚拟机通过java.exe或javaw.exe来启动一个Java虚拟机实例
JVM生命周期
Java虚拟机中存在两种线程:
- 守护线程,例GC线程
- 非守护线程,例main函数、自定义的线程
注:java虚拟机中,只要有任何非守护线程还没结束,java虚拟机的实例都不会退出。
java虚拟机的生命周期: 当一个java应用程序main函数启动时虚拟机也同时被启动,而只有当在虚拟机实例中的所有非守护进程都结束时,java虚拟机实例才结束生命。
JVM体系结构
- 类加载器(ClassLoader)
当一个ClassLoader启动时,ClassLoader的生存地点在JVM堆中,然后它会从文件系统或网络上将.class文件装载到JVM的方法区(永久区),方法区中的这个字节文件会被虚拟机拿来new一个对象实例,然后在JVM堆内生成一个字节码的对象,并且在class字节码的内存文件中有两个引用:一个指向堆中class对象实例,一个指向加载自己的ClassLoader
2.执行引擎
执行引擎是java虚拟机的最核心组件之一,它负责执行虚拟机的字节码,现代虚拟机为了提高执行效率,会使用即时编译技术将方法编译成机器码后再执行
- 方法区(永久区)
方法区,存放被类加载器装载的类信息,包括类信息(修饰符、类名等)、字段属性(修饰符、类型、字段名等)、方法信息(修饰符、回参、方法名、入参等)、类变量(就是static修饰的静态字段)等等。除了类信息外,方法区中还存放运行时的常量池信息,包括字符串字面量和数字常量
- Java堆
java堆在虚拟机启动时创建,是java程序最主要的内存工作区域。几乎所有的java对象实例都存放在java堆中。堆空间是所有线程共享的。
- Java虚拟机栈
每一个java线程都有一个私有的java虚拟机栈,它在线程创建的时候被创建,java栈中保存着栈帧信息,一个方法对应一个栈帧(包括方法的局部变量、方法参数等)
- 本地方法栈
本地方法栈,和java栈非常类似,最大的不同在于java栈用于java方法的调用,而本地方法栈则用于本地方法的调用。
总结
当一个程序启动前,它的class文件会被类加载器(ClassLoader)装入方法区(永久区),执行引擎读取方法区的字节码进行解析,边解析边运行,然后PC寄存器指向了main函数所在位置,虚拟机开始为main函数在Java虚拟机栈中预留一个栈帧,然后开始执行main函数,main函数里的代码被执行引擎映射成本地操作系统里相应的实现,然后调用本地方法接口,本地方法运行时操作系统会为本地方法分配本地方法栈,用来存储一些临时变量,然后运行本地方法,调用操作系统API等等。