志在指尖
用双手敲打未来

JVM的架构和执行过程

简介
JVM也叫JavaVirtualMachine,它是java程序运转的根底,担任将javabytecode转化成为适合在各个不同操作体系中运转的机器代码并运转。今天咱们和小师妹一同走进java的核心JVM,领略java在设计上的哲学。
JVM是一种规范
小师妹:F师兄,常常听到有人说hotspotVM,这个跟JVM是什么关系?
其实吧,JVM仅仅一种规范,就像是一种协议,只要是完成和满意这种协议的都能够称为JVM。当然,java现在是Oracle公司的,所以这些所谓的JVM规范也是由Oracle来颁布的,如果你去查看Oracle的文档,就会发现有一个专门的JavaSESpecifications栏目,这个栏目中列出了JVM的完成规范,最新的规范便是TheJavaVirtualMachineSpecification,JavaSE14Edition。
已然JVM是一个规范,就可能有许多种完成。各大公司在满意JVM规范的根底上,开发了许多个不同的版别。
下面是我在维基百科中截取到的目前各个JVM的比较:
小师妹:F师兄,大家齐心协力做一个JVM不是更好吗?为什么分来分去的,还要重复造轮子?
有听过Oracle和Google之间的API十年诉讼案吗?API都不能顺便用,更何况是JVM。各大厂商为了各自的利益,终究搞出了这么多个JVM的版别。
在这些JVM中,最常用的便是HotSpotJVM了,毕竟它是Oracle的亲儿子,或许能够说HotSpotJVM便是JVM的规范。
接下来便是EclipseOpenJ9,这个是由IBM主导的JVM,一般只能跟IBM的产品一同运用的,由于有许可证限制。
java程序的履行次序
为了说明JVM的效果,咱们先来回忆一下java程序的履行次序。
编写java代码文件比方Example.java运用java编译器javac将源文件编译成为Example.class文件JVM加载生成的字节码文件,将其转化成为机器能够识别的nativemachinecode履行JVM的架构
小师妹:F师兄,Java语言那么多特性,最后都要在JVM中运转,JVM的架构是不是特别杂乱?好怕我听不懂。
其实吧,JVM能够分为三大部分,五大空间和三大引擎,要讲起来也不是特别杂乱,先看下面的总体的JVM架构图。
从上面的图中,咱们能够看到JVM中有三大部分,分别是类加载体系,运转时数据区域和ExecutionEngine。
类加载体系
类加载体系分为三个阶段,分别是加载,链接和初始化。
加载大家都很清楚了,java中有个专门的ClassLoader来担任这个工作。除了加载Class之外,ClassLoader还能够用来加载resources。
在JDK9之前,体系默认有三个类加载器,分别是:
1.BootstrapClassLoader
这个类加载器首要是加载/jre/lib下面的rt.jar,而且这个类加载器是用C/C++来编写的,而且它是后边ExtensionClassLoader的父ClassLoader。
这个类应该在java代码中找不到的(correctmeifIamwrong!)。
2.ExtensionClassLoader
这个类加载器首要加载JDK的扩展类/jre/lib/ext,它的完成类是sun.misc.Launcher$ExtClassLoader:
咱们看下它的完成,实际上它创立了一个单例形式,运用的是两层检查加锁,小师妹能够考虑一下怎样运用延迟初始化占位类的方式来从头这个类。
3.SystemClassLoader
这个加载器是加载定义在ClassLoader中的类。它的完成类是sun.misc.Launcher$AppClassLoader,这个类的完成很长,这儿就不完好列出来了:
staticclassAppClassLoaderextendsURLClassLoader
在JDK9之后,由于引入了JPMS模块的概念,所以类加载器变得不一样了,在JDK9之后仍是有三个内置的类加载器,分别是BootClassLoader,PlatformClassLoader和AppClassLoader:
Linking阶段首要做了三件工作:
Verification-首要验证字节码文件的结构的正确性,如果不正确则会报LinkageError。Preparation-担任创立staticfields,而且初始化他们的值。Resolution-把类型的常量池中引证的类,接口,字段和办法替换为直接引证的进程。Initialization阶段首要是调用class的父类和自身的初始化办法,来设置变量的初始值。
运转时数据区域
类加载好了,也初始化了,接下来就能够准备运转了。
运转的时分要为数据分配运转空间,这便是运转时数据区域的效果。
运转时数据区域又能够分为5个部分:
1.MethodArea
办法区对错Heap的内存空间,首要用来存放class结构,staticfields,method,method’sdata和staticfields等。办法区是在JVM发动的时分创立的,而且在所有的线程中共享。
Run-TimeConstantPool运转时常量池是放在办法区中的,他是class文件中constant_pool的运转时体现。
注意在JDK8之前,HotSpotJVM中对办法区的完成叫做耐久代PermGen。不过在JDK8之后,PermGen已经被取消了,现在叫做Metaspace。Metaspace并不在java虚拟机中,它运用的是本地内存。Metaspace能够经过-XX:MaxMetaspaceSize来控制。
2.HeapArea
HeapArea首要存储类目标和数组。废物收回器(GC)首要便是用来收回HeapArea中的目标的。
3.StackArea
由于是栈的结构,所以这个区域总是LIFO(Lastinfirstout)。咱们考虑一个办法的履行,当办法履行的时分,就会在StackArea中创立一个block,这个block中持有对本地目标和其他目标的引证。一旦办法履行结束,则这个block就会出栈,供其他办法访问。
4.PCRegisters
PCRegisters首要用来对程序的履行状况进行跟踪,比方保存当时的履行地址,和下一步的地址等。
5.NativeMethods
最后一个便是本地办法区了,由于JVM的底层许多都是由C/C++来完成的,这些办法的完成就构成了本地办法区。
履行引擎
履行引擎首要担任将java的字节码翻译成机器码然后履行。
先看一个java字节码的内在结构,大家能够随意找一个编译好的类,运用javap来进行解析:
javap-vBufferUsage
这儿不过多介绍输出结果的含义,咱们会在后边的文章中进行详解。
这咱们能够看到办法中都有一个Code片段,这些Code被称为OpCode,是JVM能够理解的操作指令。
履行引擎中里面又有三个部分:
1.Interpreter
翻译器用来读取上面介绍的OpCode,并将其翻译成为机器语言。由于翻译器需求一个指令一个指令的翻译字节码,所以速度会比较慢。这便是好久好久以前Java被诟病的地方。
2.JIT(Just-In-Time)compiler
为了处理Interpreter翻译慢的问题,JDK引入了JIT,对于那些常常运用的代码,JIT会将这些字节码翻译成为机器代码,并直接复用这些机器代码,然后提高了履行效率。
3.GarbageCollector
GC用来收回HeapArea,他是一个Daemonthread。

未经允许不得转载:IT技术网站 » JVM的架构和执行过程
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载