Object o = new Object();
内存中有一个变量o指向new出来的对象,
蓝色区域代表的就是对象。
通过new创建对象时分为三步:
第一步申请分配内存,这一步给成员变量赋默认值,
第二步调用构造方法,这一步给成员变量赋初始值,
第三步建立指针与对象的关联。
第二步是为了解决c++ 变量遗留值的问题,
是上一个程序访问过这块空间遗留下的值,安全起见先赋默认值。
分为4个部分:
8个字节
4个或8个字节,指向对应的class
对象的内部数据,例如成员变量
将字节数长度拼接到可以被8整除
我们可以用JOL类库来演示一下
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core --> <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.16</version> <scope>provided</scope> </dependency>
ObjectLayout
package com.duohoob.jvm.bytecode; import org.openjdk.jol.info.ClassLayout; @SuppressWarnings("unused") public class ObjectLayout { private static class T { int a, b; } public static void main(String[] args) { T t = new T(); System.out.println(ClassLayout.parseInstance(t).toPrintable()); } }
运行
com.duohoob.jvm.bytecode.ObjectLayout$T object internals: OFF SZ TYPE DESCRIPTION VALUE 0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0) 8 4 (object header: class) 0xf800c043 12 4 int T.a 0 16 4 int T.b 0 20 4 (object alignment gap) Instance size: 24 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
多了个数组长度
对象头包含markword、class pointer信息,
markword包含hashCode信息、synchronized锁信息、GC垃圾回收标记。
GC标记包含三色标记信息和分代年龄。
堆中的是实例对象,方法区中的是类型class。
优点:垃圾回收不用频繁改动t。
缺点:慢,需要先定位到指针,再定位到对象,两次访问。
函数内的局部变量,
new的时候会先尝试在自己的栈帧内部分配空间,
例如for循环内通过new创建对象,
方法执行完毕,栈帧自动弹出,释放掉空间。
分析函数内部的创建出的对象,
除了当前栈帧还有没有被其它栈帧调用,
是否逃出了当前栈帧管控范围,
如果有则不能再栈上分配,只能分配在堆上。