引言:对于Java工程师来说,JVM一直是一个神秘的存在,对于多线程编程来说,大体都是一知半解;究其根本,一般皆是未曾深入了解一下JVM的内部机制和结构,本文讲深入剖析其中的核心内容:内部结构和启动流程
1. JVM的基本结构和组成
这个是从网络上拿过来的一个非常经典的结构图:
基于上面的图,我们可以发现JVM由:类加载系统/执行引擎/GC垃圾回收系统三个核心系统构成,另外还有内存模式或者内存空间/本地方法库,两个组件构成。
加载器系统完成Class的加载/管理, GC回收系统则使用内存模型来进行内存的回收以及优化管理; 执行引擎负责底层的Class执行的解释执行,会依赖于内存模型进行对象的创建以及管理执行,其执行核心会依赖于不同平台和操作系统的本地方法类库。
内存模型或者空间主要包括:
- 堆 分配对象的区域, 我们通常所属的GC回收模型代系结构(eden/s0/s1/tentured)就是说的这个区域
- 栈 在方法调用级别的帧栈用以存储方法调用链条,对象/方法/输入输出参数等,迭代调用的栈溢出就是这个位置
- 方法区 主要是指Permanent区域,存放Class的信息,方法体,Main方法以及常量信息(JDK 7后放到堆中)
- 本地方法栈 主要存放的是方法执行体中使用的变量和空间需求
堆区域服务于所有的线程访问和请求,栈的区域只服务于单个线程,非共享的区域。
2. 从Java Class的加载过程来看JVM的启动流程
在运行Java程序之时, 一般会进行如下操作: java xxxx.class, 下面我们来简要概述其启动的流程:
a. Java可执行程序会首先查找JRE的位置,基于其位置来寻找JRE的Home位置
b. 寻找JVM.cfg位置。
基于第一步中的JRE位置,在JRE/lib/cpu_arch(cpu的架构)/JVM.cfg下找到这个文件;通常的cpu类型有: ia64, i386, arm,x86之类。我们通常所用的windows系统一般皆是i386的架构。
在JVM.cfg中存在以下的配置信息:
- -client KNOWN (客户端模式)
- -server KNOWN (服务端模式)
- -hotspot ALIASED_TO -client (等同于client模式)
- -classic WARN (已经推出历史舞台,还有限度支持,将有可能又其它JVM的设置来替代)
- -native ERROR (不支持,报错)
- -green ERROR (不支持,报错)
c. 加载JVM.dll文件
基于LoadLibrary来加载dll文件,完成JVM的创建准备工作
d. 初始化JVM
这样就可以在Java中调用JVM的函数了.调用InvocationFunctions->CreateJavaVM也就是JVM中JNI_CreateJavaVM方法获得JNIEnv结构的实例
e. 运行Java程序
JVM初始化结束之后,在启动通过findClass等操作加载Main入口类,调用main方法执行Java程序的后续操作
讲到这里,就基本完成了一个类的加载过程,当然这里仅仅讲到了开始加载Class就结束了,着重想要描述的是JVM的启动过程,大家可以发现,java可执行程序-JRE Home -JVM.cfg --> JVM.dll --> 加载/初始化 -加载class,从而走完JVM的流程
3. 总结
以上的知识都是我们后续进行JVM的深入学习和理解的物质基础,在学习JVM的路上,我们刚刚迈出了第一步。
以上的知识都是我们后续进行JVM的深入学习和理解的物质基础,在学习JVM的路上,我们刚刚迈出了第一步。