-
问 JVM包含哪几部分?
JVM 主要由四大部分组成:ClassLoader(类加载器),Runtime Data Area(运行时数据区,内存分区),Execution Engine(执行引擎),Native Interface(本地库接口),下图可以大致描述JVM的结构
JVM是执行Java程序的虚拟计算机系统,执行过程: 首先需要准备好编译好的Java字节码文件(即class文件),计算机要运行程序需要先通过一定方式(类加载器)将class文件加载到内存中(运行时数据区),但是字节码文件是JVM定义的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解释器(执行引擎)将字节码翻译成特定的操作系统指令集交给CPU去执行,这个过程中需要调用一些不同语言为Java提供的接口(例如驱动,地图制作等),这就用到了本地native接口(本地库接口)
ClassLoader:负责加载字节码文件即class文件,class文件在文件开头有特定的文件标示,并且ClassLoader只负责class文件的加载,至于是否可以运行,则由Execution Engine决定
Runtime Data Area:是存放数据的,分为五部分:Stack(虚拟机栈),Heap(堆),Method Area(方法区),PC Register(程序计数器),Native Method Stack(本地方法栈)。几乎所有的关于Java内存方面的问题,都集中在这块。
Execution Engine:执行引擎,也叫 Interpreter。Class文件被加载后,会把指令和数据信息放入内存中,Execution Engine则负责把这些命令解释给操作系统,即将JVM指令集翻译为操作系统的指令集。
Native Interface:负责调用本地接口的,他的作用是调用不同语言的接口给Java用,他会在Native Method Stack中记录对应的本地方法,然后调用该方法时就通过Execution Engine加载对应的本地lib。原本多用于一些专业领域,如Java驱动,地图制作引擎等,现在关于这种本地方法接口的调用已经被类似于Socket通信,WebService等方式取代。 JVM的启动过程分为如下四个步骤:
- JVM的装入环境和配置
java.exe 负责查找JRE,并且它会按照如下的顺序来选择JRE
自己目录下的JRE
父级目录下的JRE
查注册中注册的JRE - 装载JVM
通过第一步找到JVM的路径后,Java.exe通过LoadJavaVM来装入JVM文件。LoadLibrary装载JVM动态连接库,然后把JVM中的到处函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMIntArgs挂接到InvocationFunction变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数指针变量上。JVM的装载工作完成 - 初始化JVM,获得本地调用接口
调用InvocationFunction->CreateJavaVM,也就是JVM中JNI_CreateJavaVM方法获得JNIEnv结构的实例 - 运行Java程序
JVM运行Java程序的方式有两种:jar包和class
运行jar的时候,java.exe调用GetMainClassName函数,该函数先获得JNIEnv实例然后调用JarFileJNIEnv类中getManifest(),从其返回的Manifest对象中取getAttrebutes(“Main-Class”)的值,即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用Java.c中的LoadClass方法装载该主类(使用JNIEnv实例的FindClass)
运行Class的时候,main函数直接调用Java.c中的LoadClass方法装载该类。
-
Java程序是怎么运行的?
写好的Java源代码经过Java编译器编译成字节码文件后,通过类加载器加载到内存中,才能被实例化,然后Java虚拟机中解释执行后,最后通过操作系统操作CPU执行获取结果,如下图