对象在JVM中的生活
在java中万事万物皆对象,而java是在JVM中进行运行的,那么对象在JVM中是如何运作的呢?我们既要知道对象是怎么来的,也要知道对象时怎么没的
先来看一下我们看到的是如何创建对象的
创建对象的几种方式
有以下几种方式
- 使用new进行实例化
1 | TestObject testObject = new TestObject(); |
- 使用Class的newInstance()
主要该方式调用的是无参的构造器,且必须是public的
1 | TestObject testObject1 = TestObject.class.newInstance(); |
- 使用Constructor的newInstance()
该方式使用的构造器根据所传类型来确定,没有权限修饰符的要求
1 | Constructor<?> constructor = TestObject.class.getConstructor(); |
- 使用clone()
需要实现Colneable接口,实现clone方法
1 | TestObject clone = (TestObject) testObject.clone(); |
- 使用反序列化
创建对象在JVM中的步骤
1 | TestObject testObject = new TestObject(); |
java编译为字节码之后为
1 | 0: new #2 // class com/zhanghe/study/jvm/TestObject |
首先会判断对应的类是否加载、链接、初始化
new指令会首先去检查这个指令的参数能否在元空间的常量值定位到一个类的符号引用,并且检查该符号引用对应的类是否已经被加载、链接、初始化,如果没有,则在双亲委派的模式下,使用当前类加载器以ClassLoader+包名+类名为key进行查找对应的class文件,如果没有找到文件,则会报ClassNotFoundException异常,如果找到,则进行类加载,生成对象额Class类对象
之后为对象分配内存
处理并发问题
初始化分配空间,所有属性设置默认值,保证对象示例字段在不赋值时可以直接使用(默认初始化)
设置对象的对象头
执行
方法进行初始化,属性的显示初始化、代码块中初始化、构造器中初始化
对象的内存布局

对象头
对象头包含有运行时元数据(包括哈希值、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳)和类型指针(指向类元数据InstanceKlass,确定该对象所属类型)
实例数据
对象真正存储的有效信息,包括程序代码中定义的成员变量的值
对齐填充
用于确保对象的总长度为8字节的整数倍