【JVM】对象的创建、内存布局、访问定位

2017-07-01  本文已影响151人  maxwellyue

仅讨论普通Java对象(不包括数组和Class对象)的创建。


对象的创建

主要分为以下几个步骤

1、检查对象对应的类是否加载

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

2、为新生对象分配内存

对象所需要的内存大小在类加载完成后便可以完全确定,此时需要从运行时数据区域中的堆中将特定大小的内存划分出来,给该对象。

3、内存空间初始化

将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在Java代码中可以不赋初值就可以直接使用,程序能够访问到这些字段的数据类型所对应的零值。

public class ObjectInit {
    private String s;
    private int a;

    @org.junit.Test
    public void test(){
        int b;
        String s1;
        System.out.println(s);  ---1
        System.out.println(a);-----2
        //System.out.println(b);----3
        //System.out.println(s1);---4
    }
}

上面的代码可以正常运行,最终打印出null和0。假如将标注3、4的两句代码去掉注释,此时运行test()方法,就会提示java:可能尚未初始化变量b和s1

4、对象设置

例如该对象是哪个类的实例、如何才能找到类的元数据信息、对象的Hash码、对象的GC分代年龄信息等。这些信息存放在对象的对象头之中。

5、对象初始化

上面的工作完成之后,一个新的对象已经产生了,但是所有的字段都还为零。一般在执行new指令之后,会接着执行<init>方法,把对象按照程序员的设定进行初始化。此时,一个真正可用的对象完全产生。


对象的内存布局(HotSpot虚拟机而言)

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

状态 存储内容 标志位
未锁定 对象哈希码、对象分代年龄 01
轻量级锁定 指向锁记录的指针 00
重量级锁定 指向重量级锁的指针 10
GC标记 空,不记录信息 11
可偏向 偏向线程ID、偏向时间戳、对象分代年龄 01

注:这里的锁定及偏向是属于线程竞争该对象时的概念


对象的访问定位

创建对象后,是通过栈上的reference数据来操作堆上的该具体对象。虚拟机规范中,reference类型数据为一个指向对象的引用,但该引用如何去定位、访问堆中的对象的具体位置则是由虚拟机实现而定的。
目前主流的访问方式是使用句柄和直接指针两种。


内容摘抄自《深入理解Java虚拟机》

上一篇 下一篇

猜你喜欢

热点阅读