对象
执行 new 指令之后会接着把对象按照程序员的意愿进行初始化(构造方法)。
- 在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为 3 块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
- 对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码(HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。
- 对象头的另外一部分是类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
- 如果对象是一个 java数组,那么在对象头中还有一块用于记录数组长度的数据。
- 第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于 HotSpot VM 的自动内存管理系统要求对对象的大小必须是8 字节的整数倍。当对象其他数据部分没有对齐时,就需要通过对齐填充来补全。
对象类型
强引用
1 2 3
| Reference r = new Reference();//强引用 r = null; // 清空引用 System.gc(); // r 将被回收
|
引用不存在时候,对象将会被回收
软引用
1 2 3 4
| SoftReference<byte[]> sr = new SoftReference(new byte[1024 * 1024 * 10]);//软引用 System.gc();//内存足够时候,对象不会被回收
byte[] data = new byte[1024 * 1024 * 15];//创建新对象,可能会导致JVM内存不足,则将回收软引用对象
|
JVM内存空间不足时候,将会回收软引用对象
弱引用
1 2
| WeakReference<Reference> wr = new WeakReference<>(new Reference());//弱引用 System.gc();//弱引用遇到GC时候,将会被回收
|
弱引用遇到GC时候,对象将会被回收
虚引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class Reference {
protected void finalize() throws Throwable { System.out.println("Object finalize..."); }
private static List<Object> LIST = new ArrayList<>(); private static ReferenceQueue<Reference> QUEUE = new ReferenceQueue();
public static void main(String[] args) { PhantomReference<Reference> ref = new PhantomReference<>(new Reference(), QUEUE);//虚引用被回收的时候,将会把对象放入队列里面去
new Thread(() -> { while (true) { LIST.add(new byte[1024 * 1024]); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ref.get()); } }).start();
new Thread(() -> { while (true) { final java.lang.ref.Reference<? extends Reference> poll = QUEUE.poll(); if (poll != null) {//虚引用被回收时候,将会被监听到 System.out.println("虚引用被回收了..."); } } }).start();
try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.gc(); } }
|
主要用在虚拟机层,管理堆外内存使用。不能单独使用,主要是用于追踪对象被垃圾回收的状态。通过PhantomReference类和引用队列ReferenceQueue类联合使用实现。