JAVA虚拟机(一):Java虚拟机运行时数据区

1、Java虚拟机运行时数据区


1.1、程序计数器

        程序计数器,线程私有,是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。

1.2、Java虚拟机栈

        Java虚拟机栈,线程私有,生命周期与线程相同。虚拟机栈描述的是方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法调用直至完成的过程,就对应一个栈帧在虚拟机栈中入栈到出栈的过程。

1.3、本地方法栈

        本地方法栈,线程私有,作用与虚拟机栈类似,是为虚拟机使用Native方法服务。

1.4、Java堆

        Java堆,线程共享,用于存放对象实例,几乎所有对象实例都在这里分配内存。

1.5、方法区

        方法区,线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

        运行时常量池,方法区的一部分,用于存放编译期生成的各种字面量和符号引用。


2、HotSpot虚拟机

2.1、对象的创建

        虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。

        在类加载检查通过后,虚拟机将为新生对象从Java堆分配一块确定大小的内存空间。

        内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头)。

        接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头中。

        在以上工作完成后,从虚拟机的视角来看,一个新的对象就产生了,但从Java程序的视角来看,对象创建才刚刚开始--<init>方法还没有执行,所有的字段都还为零。当将对象按照程序员的意愿进行初始化之后,这样一个真正可用的对象才算完全产生出来。

2.2、对象的内存布局

        对象在内存中存储的布局可用分为3块区域:对象头、实例数据和对齐填充。

        对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。对象头的另一部分是类型指针,即对象指向它的类原数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

        实例数据是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。

        对齐填充并不是必然存在的,仅仅起着占位符的作用。

2.3、对象的访问定位


        Java程序通过栈上的reference数据来操作堆上的具体对象。HotSpot虚拟机访问对象的方式采用直接指针访问,所以reference中存储的就是对象的实际地址。


注:以上内容学习自《深入理解Java虚拟机:JVM高级特性与最佳实践》。

猜你喜欢

转载自blog.csdn.net/lercent/article/details/80491164
今日推荐