Java程序的运行机制涉及到编译、加载、链接、初始化、执行等多个阶段。
-
编写代码: 开发者首先编写Java源代码,通常保存在以.java为扩展名的文件中。源代码包含了程序的逻辑和功能实现。
-
编译代码: 使用Java编译器(javac)将源代码编译为字节码文件(.class文件),字节码是一种与平台无关的中间代码。
-
加载类: Java虚拟机(JVM)通过类加载器(ClassLoader)将编译后的字节码文件加载到内存中。类加载器负责查找类文件并加载类的字节码到内存中。
-
链接阶段: 链接分为三个阶段:验证、准备和解析。
- 验证(Verification):确保加载的字节码符合Java虚拟机规范,防止恶意代码的执行。
- 准备(Preparation):为类的静态变量分配内存并设置默认初始值。
- 解析(Resolution):将符号引用替换为直接引用,即将类、方法和字段的引用转换为在方法区中的指针。
-
初始化类: 在类加载完成后,JVM会对类进行初始化。类的初始化包括执行静态变量的赋值和静态代码块的执行。这是类加载过程中的最后一步。
-
执行程序: JVM从main方法开始执行程序。主线程执行main方法中的代码,根据程序的逻辑执行相应的操作。
-
即时编译(JIT): 在运行过程中,JVM可能会将部分热点代码(经常执行的代码)编译成本地机器码,以提高执行效率。这个过程就是即时编译(JIT)。
-
垃圾回收: 在程序执行过程中,JVM中的垃圾回收器(Garbage Collector)会周期性地检测并回收不再使用的内存对象,以释放内存空间。这个过程称为垃圾回收。
-
程序结束: 程序执行完成后,JVM会释放资源并终止执行。程序执行结束后,JVM会退出。
解释执行(Interpreted Execution)和编译执行(Compiled Execution)是Java程序运行时采用的两种主要执行方式:
解释执行:
在解释执行中,Java虚拟机(JVM)逐条解释字节码并执行相应的本地机器指令。这意味着JVM在运行时不会将字节码编译成本地机器代码,而是直接解释执行字节码。这种执行方式的优点是简单、灵活,因为它不需要等待整个程序被编译完成就可以立即执行代码。然而,解释执行通常会导致较慢的性能,因为解释器需要在每次执行时都重新解释字节码。
编译执行:
在编译执行中,Java虚拟机(JVM)会将字节码动态地编译成本地机器代码,然后执行这些本地机器代码。这个过程通常由即时编译器(Just-In-Time Compiler,JIT Compiler)完成。即时编译器会对字节码进行实时的编译,将其转换成与特定硬件平台兼容的本地机器代码。这种执行方式的优点是执行速度更快,因为编译后的本地机器代码可以直接在硬件上运行,而不需要解释器逐条解释字节码。
在实际中,Java虚拟机通常会结合使用这两种执行方式。初始阶段可能会使用解释执行,以便尽快启动程序。随着程序的执行,JVM会观察哪些部分的代码频繁执行,然后对这些部分进行即时编译,以提高性能。这种动态优化的方式称为“混合执行模式”(Mixed-Mode Execution)。