概述
由 Java 和 C++ 运行方式的不同引入字节码和 Java 虚拟机的概念,最后详细描述虚拟机运行字节码的机制。
Java 和 C++ 的运行方式上的不同
Java 代码的运行方式和 C++ 的主要不同点是:编译器把 C++ 代码翻译成机器码在硬件中运行,而 Java 代码则是被转换成字节码,在 Java 虚拟机(JVM)中运行。
字节码
字节码是指令的操作码为一个字节的指令序列,存放在 .class 文件中。
Java虚拟机
Java虚拟机在不同的硬件平台上有软件实现,甚至也可以直接由硬件实现。字节码可以在这些不同平台上的虚拟机运行,这就体现了 Java 的可移植性。
虚拟机还提供了一个运行代码的托管环境(Managed Runtime),包括自动内存管理和垃圾回收等,这里需要了解,虚拟机在运行时会把内存分为几个有特定用途的区域:Java 方法栈、本地方法栈、PC寄存器、方法区和堆。
运行机制
先把 .class 文件加载进来,把加载后的类放入到方法区。运行的时候一般采用两种模式混合的策略来执行方法区的代码,这两种模式分别是解释执行和即时编译。
解释执行
逐条翻译字节码为机器码,并交给硬件运行
即时编译
针对经常被调用的热点代码,以一个方法为单位,将其中所有字节码编译为机器码存放在方法区,在下一次执行到该方法时直接使用已编译好的机器码即可。
因为执行效率高的机器码需要使用更多的时间进行编译,所以即时编译一般是在额外的编译线程中执行,
同时,为了在执行效率和编译时间上做取舍,虚拟机一般会提供多个即时编译器完成这项工作,通常有两种:C1和C2。C1的编译时间短,C2的执行效率高,根据它们的特点,它们分别适用于对启动性能有要求的客户端程序和对峰值性能有偏好的服务器程序,所以它们分别又被称为 Client 和 Server 编译器。
一般对于热点代码会用C1编译,然后其中使用频率更频繁的代码会用C2再次编译,以达到更高的效率。
混合策略
对于大部分运行次数很少的代码只使用解释执行,而对于频繁使用的代码,在进行解释执行的基础上,使用另外的编译线程进行即时编译,在下次使用时直接使用即时编译后的结果即可。
结论
Java虚拟机执行字节码的策略既节省内存又在热点代码上提高执行效率,非常有意思,值得我们学习。