java虚拟机启动器,java虚拟机运行java程序的基本过程
一、前言二。Java虚拟机(1)配置JVM加载环境(2)分析命令行参数(3)执行main方法1,创建新的JVM实例2,加载入口类3,找到main方法4,执行main方法3,分析字节码(1)解释字节码1,基于栈指令集2,编译字节码1和基于寄存器指令集2的C1。
00-1010我们在编写Java应用的时候,很少关注Java程序是如何被操作系统运行和管理调度的。带着好奇心,探索Java虚拟机的启动过程。
00-1010从Java源代码、Java字节码、Java虚拟机、操作系统四个角度分解启动过程。
public class hello world { public static void main(String[]args){ system . out . println( hello world!);}}
目录
利用Java环境提供的可执行命令javac将源代码编译成字节码文件。编译后的字节码文件是独立于平台的,可以跨平台运行。注意,discribe javac命令是一个独立的编译应用程序。当源代码被编译时,该过程终止。java命令启动的虚拟机进程的编译过程是将字节码指令编译成汇编指令(二进制指令)。
一、序言
Java字节码不能直接在操作系统上创建进程,需要借助已启动的虚拟机进程来解析字节码。处理字节码有两种常见的方法:解释型和编译型。
命令行中的每个java命令都会启动一个Java虚拟机进程,每个虚拟机都是相互独立的。虚拟机进程由命令行参数配置。
Java虚拟机准备启动后,可以依次解析字节码指令,正式运行Java代码部分。
00-1010操作系统通过进程管理和调度Java虚拟机,无法感知虚拟机间接解析Java字节码。Java字节码通过虚拟机的抽象运行在操作系统上。
00-1010运行Java应用时,需要先安装Java环境。但是,安装的Java环境和Java应用程序有什么关系呢?Java应用程序是如何运行的?让我们找出答案。
二进制可执行程序${JAVA_HOME}/bin/java用C语言编写,由GCC编译器编译。探究Java虚拟机的运行原理,首先需要找到相应的源代码。
当您安装Java环境时,您会看到一个src.zip压缩文件。解压后,里面的launcher/java.c文件就是可执行java命令的主要源代码。
虚拟机的启动入口位于launcher/java.c的main方法中整个过程分为以下几个步骤:配置JVM加载环境;正在解析虚拟机参数;设置线程堆栈大小;执行Java main方法
00-1010从操作系统加载环境变量、硬件信息等运行环境信息,为后续创建JVM进程做准备。
00-1010加载JVM环境后,需要在启动时解析命令行参数。这个过程是通过ParseArguments方法实现的,调用AddOption方法将解析后的参数保存到JavaVMOption中。
例如,在此步骤中解析公共JavaVMOption参数:
-Xms:设置InitialHeapSize值,这也是堆的最小值;-Xmx:设置最大MaxHeapSize堆的;
JVM调优参数的分析在这一步完成。
00-1010线程栈大小确定后,通过ContinueInNewThread方法创建一个新线程,执行JavaMain函数。大致过程如下:
00-1010初始化JVM方法调用InvocationFunctions的CreateJavaVM方法,即调用JVM.dll函数JNI_CreateJavaVM创建新的JVM实例,这是一个复杂的过程。
h4>2、加载入口类通常在命令行中运行如下命令即指明入口类路径
# 直接指名入口类路径java HelloWorld.class# 通过包类配置入口类路径java -jar HelloWorld.jar
3、查找main方法
通过GetStaticMethodID方法查找指定main方法名的静态方法。
4、执行main方法
通过JavaCalls::call
回调执行main方法。需要注意的是,这里执行main方法不是Java语言的方法,是经过虚拟机解释(或者编译)后,操作系统能够理解的二进制可执行方法。
三、解析字节码
(一)解释字节码
1、基于栈指令集
iconst_1 将 1 放入栈顶iconst_1 将 1 放入栈顶iadd 将栈顶的 2 个数相加后结果放入栈顶istore_0 将相加的结果放入局部变量表
基于栈的指令集优点是虚拟机解释器是可跨平台移植的,换句话说不同平台的虚拟机解释器代码可以复用。
2、基于寄存器指令集
mov eax,1 把 EAX 寄存器的值设为 1add eax,1 再把这个值加 1 ,结果保存在了 EAX 寄存器
基于寄存器指令集的优点是执行速度相对于栈较快,原因是出栈入栈本身就涉及了大量的指令,而且栈是在内存中实现的,更底层的汇编指令性能更高。
基于寄存器指令集的缺点是虚拟机解释器是不可跨平台移植,需要针对不同平台的虚拟机做不同实现。考虑到不同平台已经使用不同的虚拟机程序,因此此过程多用户透明。
虚拟机通过解释器来翻译字节码文件中的指令比较顺其自然,可是对于服务器端高频执行的程序来说,中间的翻译过程相对耗时。解释字节码的方式适用于对启动性能要求高,并且执行频率较低的应用程序。
(二)编译字节码
最初,JVM 中的字节码是由解释器( Interpreter )完成编译的,当虚拟机发现某个方法或代码块的运行特别频繁的时候,就会把这些代码认定为热点代码
。
为了提高热点代码的执行效率,在运行时,即时编译器(JIT,Just In Time)会把这些代码编译成与本地平台相关的机器码,并进行各层次的优化,然后保存到内存中。
在 HotSpot 虚拟机中,内置了两种 JIT,分别为C1 编译器
和C2 编译器
,这两个编译器的编译过程是不一样的。
1、C1 编译器
C1 编译器是一个简单快速的编译器,主要的关注点在于局部性的优化,适用于执行时间较短或对启动性能有要求的程序,也称为Client Compiler
,例如,GUI 应用对界面启动速度就有一定要求。
2、C2 编译器
C2 编译器是为长期运行的服务器端应用程序做性能调优的编译器,适用于执行时间较长或对峰值性能有要求的程序,也称为Server Compiler
,例如,服务器上长期运行的 Java 应用对稳定运行就有一定的要求。
3、分层编译
分层编译将 JVM 的执行状态分为了 5 个层次:
第 0 层:程序解释执行,默认开启性能监控功能(Profiling),如果不开启,可触发第二层编译;第 1 层:可称为 C1 编译,将字节码编译为本地代码,进行简单、可靠的优化,不开启 Profiling;第 2 层:也称为 C1 编译,开启 Profiling,仅执行带方法调用次数和循环回边执行次数 profiling 的 C1 编译;第 3 层:也称为 C1 编译,执行所有带 Profiling 的 C1 编译;第 4 层:可称为 C2 编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。
通常情况下,C2 的执行效率比 C1 高出30%以上。
在 Java8 中,默认开启分层编译。如果只想开启 C2,可以关闭分层编译(-XX:-TieredCompilation
),如果只想用 C1,可以在打开分层编译的同时,使用参数:-XX:TieredStopAtLevel=1
。
通过 java -version
命令行可以查看到当前虚拟机解析字节码的方式,mixed mode
表示既有解释模式也有即是编译模式。
java version "1.8.0_261"Java(TM) SE Runtime Environment (build 1.8.0_261-b12)Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)
mixed mode
代表是默认的混合编译模式,除了这种模式外,我们还可以使用-Xint
参数强制虚拟机运行于只有解释器的编译模式下;也可以使用参数-Xcomp
强制虚拟机运行于只有 JIT 的编译模式下。
仅使用解释模式
通过命令java -Xint -version
设置仅使用解释模式,interpreted mode
表示解释模式。
java version "1.8.0_261"Java(TM) SE Runtime Environment (build 1.8.0_261-b12)Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, interpreted mode)
仅使用编译模式
通过命令java -Xcomp -version
设置仅使用编译模式,compiled mode
表示编译模式。在编译模式下,程序启动能感觉到明显的卡顿。
java version "1.8.0_261"Java(TM) SE Runtime Environment (build 1.8.0_261-b12)Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, compiled mode)
四、小结
通过对Java虚拟机启动过程的解析,特别是即时编译
环节的理解,Java应用运行并不慢。当应用中热点代码普遍被编译成汇编指令(二进制可执行命令)存放于内存中时,可近似达到C语言原生程序的运行速度。
随着算力与内存成本日渐降低,通过空间复杂度置换时间复杂度的策略显然是合理的,使用Java语言编写需求万千变化的应用是第一选择:既有跨平台、内存安全、框架生态丰富的优点,也在运行效率方面积极改善,这种折中选择与市场反馈保持一致。
到此这篇关于Java虚拟机启动过程解析的文章就介绍到这了,更多相关Java虚拟机启动内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。