深入理解Java虚拟机 JVM基本框架

JVM基本框架

首先是JVM的整图结构图:
《深入理解Java虚拟机 JVM基本框架》

围绕JVM内存空间有三个重要的组成部分(绿色框):

另外的内容还包括:

  • Javac编译器(.java源程序如何如何编译成类文件?java的语法糖?)
  • 程序的并发执行

JVM内存空间

三个重要组成部分都是围绕JVM运行时的内存模型展开,因此先简单介绍这部分。

  • 虚拟机栈:虚拟机栈描述的是方法Method执行的内存模型:每个方法被调用时都会创建一个栈帧,存放方法局部变量表、操作数栈和动态链接,方法出口地址。栈帧结构如下:
    《深入理解Java虚拟机 JVM基本框架》

    • 每个线程都有私有的栈帧空间,相互独立。
    • 当前执行方法拥有顶部当前栈帧,方法的调用和返回过程就是栈帧的入栈和出栈过程。
    • 局部变量表:基本数据类型和对象引用局部变量、方法参数和隐含的this指针。
    • 操作数栈:JVM字节码指令集是基于操作数栈的(就像x86硬件指令集基于通用寄存器一样)。
    • 虚拟机栈可通过VM参数-Xss(每个线程栈尺寸)设置栈空间大小,如果当前线程申请的栈深度大于虚拟机允许的深度,StackOverFlowError异常。
  • 本地方法栈:与虚拟机栈类似,只是服务对象是Native方法。

  • 程序计数器:当前线程代码执行指示器,每个线程独立。
  • :几乎所有对象实例在堆中分配空间(栈上只是堆中实例的引用),为所有线程共享。
    • 堆是垃圾收集器GC的主要管理区域(在讲到GC时会有堆上空间的细分)
    • JIT编辑器的逃逸技术等,使某些对象也能够在栈上分配空间。
  • 方法区:存放被加载的类信息、常量(final类型常量,常量池)、静态变量、即时编译器编译后的本地代码。

    • HotSpot JVM用持久代(Permanet Generation)来存放方法区。
    • 方法去垃圾回收主要是常量池回收和类型卸载。

    [运行时常量池](Runtime Constant Pool)

    • 是方法区一部分,与Class文件中[常量池](Constant Pool Table)相对应,当类加载后,Class文件的[常量池]将存放在[运行时常量池]中。
    • [常量池]存放编译期生成的字面量(字符串”abc”,声明为final常量等)和符号引用(类和接口全限定名、字段名、方法名等)。

对象的内存布局和创建

1)堆是对象存储区域,那么一个对象内存布局是怎样的?

《深入理解Java虚拟机 JVM基本框架》

下面是IBM关于对象内存的例子。
详见:http://www.slideshare.net/cnbailey/memory-efficient-java
《深入理解Java虚拟机 JVM基本框架》

2)虚拟机如何能够解读对象实例数据?即虚拟机如何知道对象中各字段具体偏移?

  • 将类信息指针置于对象头内,如上图。klass pointer指向方法区内对象类型元数据。这也是HotSpot的做法。
    《深入理解Java虚拟机 JVM基本框架》

  • 通过句柄。
    《深入理解Java虚拟机 JVM基本框架》

    3)对象如何创建?

Point originOne = new Point(0,0);

《深入理解Java虚拟机 JVM基本框架》
关于对象的初始化,文章解析 Java 类和对象的初始化过程是这么讲的:

在类被装载、连接和初始化,这个类就随时都可能使用了。对象实例化和初始化是就是对象生命的起始阶段的活动,在这里我们主要讨论对象的初始化工作的相关特点。
Java 编译器在编译每个类时都会为该类至少生成一个实例初始化方法–即 “<init>()” 方法。此方法与源代码中的每个构造方法相对应,如果类没有明确地声明任何构造方法,编译器则为该类生成一个默认的无参构造方法,这个默认的构造器仅仅调用父类的无参构造器,与此同时也会生成一个与默认构造方法对应的 “<init>()” 方法.
通常来说,<init>() 方法内包括的代码内容大概为:调用另一个<init>() 方法;对实例变量初始化;与其对应的构造方法内的代码。
如果构造方法是明确地从调用同一个类中的另一个构造方法开始,那它对应的 <init>()方法体内包括的内容为:一个对本类的 <init>()方法的调用;对应用构造方法内的所有字节码。
如果构造方法不是通过调用自身类的其它构造方法开始,并且该对象不是 Object 对象,那<init>() 法内则包括的内容为:一个对父类 <init>()方法的调用;对实例变量初始化方法的字节码;最后是对应构造子的方法体字节码。
如果这个类是 Object,那么它的 <init>() 方法则不包括对父类 <init>() 方法的调用。

    原文作者:java虚拟机
    原文地址: https://blog.csdn.net/isunn/article/details/50487329
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞