深入理解JVM-Java代码如何运行
Java作为一种高级编程语言以其较高的可移植性被广泛使用在各个平台。那么它底层运行的原理是什么?
认识JRE和JDK
JRE(Java Runtime Environment):Java运行时环境。Java的所有执行都离不开JRE。JRE包含了Java虚拟机和Java核心类库等。
JDK(Java Development Kit):Java开发工具包。同样包含了JRE,并且还附带了一系列开发,诊断工具。
Java虚拟机具体是如何运行Java字节码的
- 执行Java代码首先要将它编译成class文件加载到Java虚拟机中。
- 加载后的Java类会被存放于方法区(Method Area)中。
- 实际运行时虚拟机会执行方法区中的代码。
- Java虚拟机会在内存中划分出堆和栈来存储运行时数据。
- Java虚拟机会将栈细分为:
- 面向Java方法的Java方法栈(也叫Java虚拟机栈)。
- 面向本地方法的本地方法栈(用C++写的Native方法)。
- 以及存放各个线程执行位置的PC寄存器。
- Java虚拟机会将栈细分为:

运行过程当中,每当调用进入一个Java方法,Java虚拟机会在当前线程的Java方法栈中生成一个栈帧,用于存放局部变量以及字节码的操作数。这个栈帧大小是提前计算好的,而且Java虚拟机不要求栈帧在内存空间里连续分布。
退出执行方法时,不管是正常还是异常都会弹出当前线程栈帧,并舍弃。
硬件执行是需要Java虚拟机将字节码翻译成为机器码:
- 解释执行:逐条将字节码翻译成为机器码并执行。优势:无需等待编译。
- 即时编译(Just-In-Time Compilation, JIT):即将一个方法中包含的所有字节码编译成为机器码后再执行。优势:实际运行速度更快
HotSpot采用的是混合模式:会对热点代码进行即时编译(JIT)。
Java虚拟机的运行效率
二八定律:即时编译建立在程序符合二八定律的假设上,即百分之二十的代码占据了百分之八十的计算资源。
对于大部分不常用的代码,无需耗费时间将其编译成机器码,而是采取解释执行。
对于近占据小部分的热点代码,可以将其编译成为机器码。
即时编译器:C1,C2和Graal(Java10引入)
C1编译器:又叫Client编译器,面向的是对启动性能有要求的客户端GUI程序,采用的优化手段较少。
C2编译器:又叫Server编译器,面向的是对峰值性能有要求的服务器端程序,采用的优化手段较为复杂。编译时间长,但是生成的代码执行效率高。
Java7开始HotSpot默认采用的是分层编译:热点方法首先会被C1编译,而后热点中的热点会被C2进一步编译。
总结
- Java虚拟机Jvm:提供了可移植性:一次书写,处处运行。
- 代替我们管理了内存。
- 为了提高效率采用了混合编译。