最近看了《深入理解Java虚拟机》,把其中重要的知识点记录下来。

1、运行时数据区

  在Java虚拟机中有下面几个运行时数据区:虚拟机栈、本地方法栈、程序计数器、方法区、堆。 

1.1程序计数器

  当前线程执行字节码的行号指示器。Java虚拟机的多线程是通过线程轮流切换获取内核资源执行的,对于同一个内核,每个时间都只有一个线程在那里执行。程序计数器的作用是让线程在切换后能回到之前的执行位置上。

1.2Java虚拟机栈

  虚拟机栈的生命周期和线程相同。每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。局部变量表存放了编译器可知的各种基本数据类型、对象引用(reference类型,可能指向对象地址的引用指针,也可能指向代表对象的句柄)。

int a = 12;
Person b = new Person();

  上面这个代码,其中a是变量,12是a这个变量指向的数据。如果是基础类型,那么变量和数据的内存是在同一个地方,都在虚拟机栈或方法区或堆中,而如果是引用类型,比如变量b会和对应数据new Person()的内存地址或句柄地址放在一起,new Person()的实例数据会放在堆中。

1.3本地方法栈

  和虚拟机栈发挥作用类似,不过本地方法栈为Native方法服务,有的虚拟机会把虚拟机栈和本地方法栈合二为一,比如HotSpot虚拟机。

1.4Java堆

  存放对象实例的地方,是垃圾收集器管理的主要区域。

1.5方法区

  存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。其中运行时常量池就是放在方法区中。

1.6直接内存

  直接内存不是虚拟机运行时数据区的一部分,JDk1.4新加入了NIO类,可以使用Native函数库直接分配堆外内存。

2、对象的内存布局

  在HotSpot虚拟机中,对象在内存中的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。

2.1对象头

  对象头包括2部分信息:

(1)Mark Word:存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。

(2)类型指针:对象指向方法区中它的类元数据的指针,虚拟机通过这个来确定这个对象是哪个类的实例。

(3)如果对象是一个Java数组,在对象中还有一块用于记录数组长度的数据。

2.2实例数据

  用于存储对象实例的各种字段内容,自身类的和父类继承的都会记录下来。

2.3对齐填充

  对象的大小必须是8字节的整数倍,如果不是整数倍就使用对齐填充补全。

2.4对象的访问对位

  Java程序通过虚拟机栈上的对象引用(reference类型)来操作堆上的具体对象,对象访问方式取决于虚拟机实现,主流的访问方式有使用句柄和直接指针2种。

(1)使用句柄访问:Java堆中划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据地址信息和类型数据的地址信息。

(2)使用直接指针访问:reference存储的是对象地址,即对象类型数据的地址信息和实例数据。HotSpot虚拟机使用的是直接指针访问方式。

  使用句柄访问最大好处是在对象被移动时不会改变对象引用,只是改变句柄的实例数据指针;使用直接指针的最大好处是速度快,节省了一次指针定位的时间开销。

posted on 2019-06-15 15:05  浮音  阅读(134)  评论(0编辑  收藏  举报