JAVA虚拟机-Java体系结构及hotspot介绍(一)

 

1、HotSpot JVM标准结构

 

最上层:javac编译器将编译好的字节码class文件,通过java 类装载器 执行机制,把对象或class文件 存放在 jvm划分内存区域

中间层:从左至右  方法区(持久代也叫非堆)、堆(共享,GC回收对象区域)、栈、程序计数器和寄存器、本地栈(私有)

最下层:jvm最核心两块 JIT(just in time)即时编译器 和 GC(Garbage Collection,垃圾回收器)

java执行流程:

 

2.运行时数据区域Runtime Data Areas

 

 2.1 JVM是什么?

 官方的说法:“Java 虚拟机具有一个,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。

JVM主要管理两种类型的内存:堆和非堆。

就是Java代码可及的内存,是留给开发人员使用的;

非堆就是JVM留给 自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法 的代码都在非堆内存中。

 

2.2 堆内存分配?

 

内存计算公式:

总内存 = 堆内存(Xmx)+方法区内存(MaxPermSize)+栈内存(Xss)*线程数+直接内存(MaxDirectMemorySize,堆外)+虚拟机内存

  1. 配置程序JVM参数如下: -Xmx20M -Xms20M -Xmn10M -XX:SurvivorRatio=8 -XX:PermSize=10M -XX:MaxPermSize=10M  -Xss512k
  2. 实际内存分配:
           PS Young Generation(10M ,eden:from survivor:to survivor=8:1:1)
                     Eden Space: 8M    From Space:(1.0MB)  To Space:(1.0MB)
           PS Old Generation (10M)
           PS Perm Generation(10M)

 2.3 堆内存参数设置?

 

详细参数配置参考:

 

3.执行引擎(Execution Engine)

 3.1 解释器和JIT执行原理

       java文件转化为机器码过程:

      

      interpreter:解释器

      JIT:即时编译器

  通过类装载器装载的,被分配到JVM的运行时数据区的字节码会被执行引擎执行。执行引擎以指令为单位读取Java字节码。它就像一个CPU一 样,一条一条地执行机器指令。每个字节码指令都由一个1字节的操作码和附加的操作数组成。执行引擎取得一个操作码,然后根据操作数来执行任务,完成后就继 续执行下一条操作码。

  不过Java字节码是用一种人类可以读懂的语言编写的,而不是用机器可以直接执行的语言。因此,执行引擎必须把字节码转换成可以直接被JVM执行的语言。字节码可以通过以下两种方式转换成合适的语言。

  • 解释器(解释执行):一条一条地读取,解释并且执行字节码指令。因为它一条一条地解释和执行指令,所以它可以很快地解释字节码,但是执行起来会比较慢。这是解释执行的语言的一个缺点。字节码这种“语言”基本来说是解释执行的。
  • 即时(Just-In-Time)编译器(编译执行): 即时编译器被引入用来弥补解释器的缺点。执行引擎首先按照解释执行的方式来执行,然后在合适的时候,即时编译器把整段字节码编译成本地代码。然后,执行引 擎就没有必要再去解释执行方法了,它可以直接通过本地代码去执行它。执行本地代码比一条一条进行解释执行的速度快很多。编译后的代码可以执行的很快,因为 本地代码是保存在缓存里的。

  

        不过,用JIT编译器来编译代码所花的时间要比用解释器去一条条解释执行花的时间要多。因此,如果代码只被执行一次的话,那么最好还是解释执行而不是编译后再执行。因此,内置了JIT编译器的JVM都会检查方法的执行频率,如果一个方法的执行频率超过一个特定的值的话,那么这个方法就会被编译成本地代码。


图 7:Java编译器和JIT编译器

  JVM规范没有定义执行引擎该如何去执行。因此,JVM的提供者通过使用不同的技术以及不同类型的JIT编译器来提高执行引擎的效率。

  大部分的JIT编译器都是按照下图的方式来执行的:


图 8: JIT编译器

  JIT编译器把字节码转换成一个中间层表达式,一种中间层的表示方式,来进行优化,然后再把这种表示转换成本地代码。

  Oracle Hotspot VM使用一种叫做热点编译器的JIT编译器。它之所以被称作”热点“是因为热点编译器通过分析找到最需要编译的“热点”代码,然后把热点代码编译成本地代码。如果已经被编译成本地代码的字节码不再被频繁调用了,换句话说,这个方法不再是热点了,那么Hotspot VM会把编译过的本地代码从cache里移除,并且重新按照解释的方式来执行它。Hotspot VM分为Server VM和Client VM两种,这两种VM使用不同的JIT编译器。


Figure 9: Hotspot Client VM and Server VM

 

  Client VM 和Server VM使用完全相同的运行时,不过如上图所示,它们所使用的JIT编译器是不同的。Server VM用的是更高级的动态优化编译器,这个编译器使用了更加复杂并且更多种类的性能优化技术。

  IBM 在IBM JDK 6里不仅引入了JIT编译器,它同时还引入了AOT(Ahead-Of-Time)编译器。它使得多个JVM可以通过共享缓存来共享编译过的本地代码。简而言之,通过AOT编译器编译过的代码可以直接被其他JVM使用。除此之外,IBM JVM通过使用AOT编译器来提前把代码编译器成JXE(Java EXecutable)文件格式来提供一种更加快速的执行方式。

  大部分Java程序的性能都是通过提升执行引擎的性能来达到的。正如JIT编译器一样,很多优化的技术都被引入进来使得JVM的性能一直能够得到提升。最原始的JVM和最新的JVM最大的差别之处就是在于执行引擎。

  

 相关文章:

 

 详细可参考:

oracle官网:Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide

并发编程网: 

Java HotSpot VM中的JIT编译

 

JVM性能优化(一)JVM技术入门

csdn:

深入理解JVM内幕 

猜你喜欢

转载自yanan0628.iteye.com/blog/2281031