Daily sentence

The wise have no doubts, the virtuous have no worries, and the brave have no fear. — Confucius

If the profile

I don’t know if you like my new theme, but I call it windmill theme. Haha, if YOU like it, we can discuss it together and make some better themes for you. Next, I will introduce today’s theme content to you: The classification of references is a very important topic for GC and JVM to understand how objects are controlled by GC and JVM

Classification of Java references

The main reference types of Java objects are: Strong reference (New), soft reference (soft), weak reference (weak), virtual reference (planTom) and finalizer reference (PlanTom).

Strong reference

As long as it can be found through GC Roots’ reference chain, it will not be garbage collected. This means that an object can only be garbage collected if all GC Roots objects do not reference it through strong references. Otherwise, it will not be garbage collected even in OOM.

Case analysis

Set JVM memory to 20M:

public class Test2 {
    public static final int _4MB=4*1024*1024;
    public static void main(String[] args) throws IOException {
        List<byte[]> list =new ArrayList<>();
        for(int i=0; i<5; i++){ list.add(new byte[_4MB]); } System.in.read(); }}Copy the code

Running the above program causes a memory overflow problem, which means that some memory is occupied even if it is not important:


Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at pers.zhb.test.Test2.main(Test2.java:12)
Copy the code

Soft references

SoftRefence objects are used in Java to represent soft references, and if an object is associated with a soft reference, the JVM will only reclaim that object if it is out of memory.

Case analysis


public class Test2 {
    private static final int _4MB=4*1024*1024;
    public static void main(String[] args) throws IOException {
        soft();
    }
    public static void soft(a){
        List<SoftReference<byte[]>> list=new ArrayList<>();
        for(int i=0; i<5; i++){ SoftReference<byte[]> reference=new SoftReference<>(
            new byte[_4MB]);
            System.out.println(reference.get());
            list.add(reference);
            System.out.println(list.size());
        }
        System.out.println("End of loop:"+list.size());
        for(SoftReference<byte[]> reference:list){ System.out.println(reference.get()); }}}Copy the code

Running results:

[B@1b6d3586 1 [B@4554617c 2 [B@74a14482 3 [GC (Allocation Failure) [PSYoungGen: 1744K-> 148k (14144K)] 14032K-> 14932k (19968K), 0.0427814secs] [Times: User =0.00 sys=0.00, real=0.05 secs] [B@1540e19d 4 [GC (Allocation Failure) --[PSYoungGen: 4696K->4696K(6144K)] 17140K->17140K(19968K), 0.00302222secs] [Times: Sys =0.00, real=0.00 secs] [Full GC (Ergonomics) [PSYoungGen: 4696K->4574K(6144K)] [ParOldGen: 12444K->12414K(13824K)] 12140K ->16988K(19968K), [Metaspace: 3118K->3118K(1056768K)], 0.009540secs] [Times: User =0.00 sys=0.00, real=0.01 secs] [GC (Allocation Failure) --[PSYoungGen: 4574K->4574K(6144K)] 16988K->16996K(19968K), 0.0010492 secs] [Times: User =0.00 sys=0.00, real=0.00 secS] [Full GC (Allocation Failure) [PSYoungGen: 4574K->0K(6144K)] [ParOldGen: 12422K->587K(8704K)] 16996K->587K(14848K), [Metaspace: 3118K->3118K(1056768K)], 0.0076471 secs] [Times: User =0.03 sys=0.00, real=0.01 secs] [B@677327b6 5 loop end: 5 null null null null [B@677327b6 Heap PSYoungGen total 6144K, used 4546K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000) eden space 5632K, 80%, informs [x00000000ff980000 0, 0 x00000000ffdf0940, 0 x00000000fff00000) from space 512 k, 0%, informs [x00000000fff80000 x00000000fff00000 0, 0 x00000000fff00000, 0) to space 512 k, 0%, informs [x00000000fff80000 0, 0 x00000000fff80000, 0 x0000000100000000) ParOldGen total 8704 k, used 587K [0x00000000fec00000, 0x00000000ff480000, 0x00000000ff980000) object space 8704K, 6%, informs [x00000000fec00000 0, 0 x00000000fec92d20, 0 x00000000ff480000) Metaspace informs the 3224 k, capacity 4500 k, committed 4864K, reserved 1056768K class space used 349K, capacity 388K, committed 512K, reserved 1048576KCopy the code

conclusion

As you can see, the garbage collection is triggered on the fourth and fifth times, and only the fifth soft reference object exists after the collection is traversed, that is, the previous virtual reference object is garbage collected when the memory is out

Soft references and reference queues

public class Test2 {
    private static final int _4MB=4*1024*1024;
    public static void main(String[] args) throws IOException {
        List<SoftReference<byte[]>> list=new ArrayList<>();
        // Reference queue
        ReferenceQueue<byte[]> queue=new ReferenceQueue<>();
        for(int i=0; i<5; i++){// The soft reference is added to the reference queue when its associated byte array is reclaimed
            SoftReference<byte[]> reference=new SoftReference<>(new byte[_4MB],queue);
            System.out.println(reference.get());
            list.add(reference);
            System.out.println(list.size());
        }
        // Retrieves unwanted soft reference objects from the queue and removes them
        Reference<? extends byte[]> poll=queue.poll();
        while(poll! =null){
            list.remove(poll);
            poll=queue.poll();
        }
        System.out.println("End of loop");
        for(SoftReference<byte[]> reference:list){ System.out.println(reference.get()); }}}Copy the code

test

[B@1b6d3586 1 [B@4554617c 2 [B@74a14482 3 [GC (Allocation Failure) [PSYoungGen: [Times: 1414K -> 1414k] 1415K -> 14964k [Times: 1414k] 1415K -> 14964k [Times: 1414k] User =0.00 sys=0.00, real=0.00 secs] [B@1540e19d 4 [GC (Allocation Failure) --[PSYoungGen: 4696K->4696K(6144K)] 17172K->17180K(19968K), 0.0011250 secs] [Times: Sys =0.00, real=0.00 secs] [Full GC (Ergonomics) [PSYoungGen: 4696K->4564K(6144K)] [ParOldGen: 12484K->12458K(13824K)] 17180K-> 1722K (1996k), [Metaspace: 3228K->3228K(1056768K)], 0.00556secs] [Times: User =0.00 sys=0.00, real=0.01 secs] [GC (Allocation Failure) --[PSYoungGen: 1212K -> 1212k [Times: 1212k] 1212k -> 1212k [Times: 1212k] 1212k -> 1212k [Times: 1212k] User =0.00 sys=0.00, real=0.00 secS] [Full GC (Allocation Failure) [PSYoungGen: 4564K->0K(6144K)] [ParOldGen: 12466K->620K(8704K)] 1230K ->620K(14848K), [Metaspace: 3228K->3228K(1056768K)], 0.0065061 secs] [Times: User =0.00 sys=0.01, real=0.01 secs] [B@677327b6 5 Loop end [B@677327b6 Heap PSYoungGen total 6144K, used 4546K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000) eden space 5632K, 80%, informs [x00000000ff980000 0, 0 x00000000ffdf0918, 0 x00000000fff00000) from space 512 k, 0%, informs [x00000000fff80000 x00000000fff00000 0, 0 x00000000fff00000, 0) to space 512 k, 0%, informs [x00000000fff80000 0, 0 x00000000fff80000, 0 x0000000100000000) ParOldGen total 8704 k, used 620K [0x00000000fec00000, 0x00000000ff480000, 0x00000000ff980000) object space 8704K, 7%, informs [x00000000fec00000 0, 0 x00000000fec9b160, 0 x00000000ff480000) Metaspace informs the 3237 k, capacity 4500 k, committed 4864K, reserved 1056768K class space used 351K, capacity 388K, committed 512K, reserved 1048576KCopy the code

A weak reference

If an object is associated with a weak reference, then when the JVM does garbage collection, it will reclaim that object regardless of whether there is sufficient memory.

Case analysis


public class Test2 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) throws IOException {
        List<WeakReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            WeakReference<byte[]> reference = new WeakReference<>(new byte[_4MB]);
            list.add(reference);
            for (WeakReference<byte[]> w : list) {
                System.out.println(w.get());
            }
            System.out.println();
        }
        System.out.println("End of loop:"+ list.size()); }}Copy the code

test

[B@1b6d3586 [B@1b6d3586 [B@4554617c [B@1b6d3586 [B@4554617c [B@74a14482 [GC (Allocation Failure) [PSYoungGen: [Times: 146k -> 146K] 146K -> 146k [Times: 146k] The user sys = = 0.00 0.00, Real =0.00 secs] [B@1b6d3586 [B@4554617c [B@74a14482 [B@1540e19d [GC (Allocation Failure)] [PSYoungGen: [Times: 3305K -> 3305k] 3305k -> 3305k [Times: 3305k] 3305k -> 3305k [Times: 3305k] 3305k -> 3305k [Times: 3305k] The user sys = = 0.00 0.00, Real =0.00 secs] [B@1b6d3586 [B@4554617c [B@74a14482 null [B@677327b6 [GC (Allocation Failure)] [PSYoungGen: [Times: 145k -> 145k] 165K -> 165k [Times: 145k] 165k -> 165k [Times: 145k] 165k -> 165k [Times: 145k] 165k -> 165k [Times: 145k] The user sys = = 0.00 0.00, Real =0.00 secs] [B@1b6d3586 [B@4554617c [B@74a14482 null null [B@14ae5a5 [GC (Allocation Failure)] [PSYoungGen: [Times: 147k -> 147k] 14726K -> 14736k [Times: 147k] 14726k -> 14736k [Times: 147k] 14726k -> 14736k [Times: 147k] The user sys = = 0.00 0.00, Real =0.00 secs] [B@1b6d3586 [B@4554617c [B@74a14482 null NULL NULL [B@7f31245a [GC (Allocation Failure)] [PSYoungGen: [Times: 1010K -> 1010k] 1010K -> 1010k [Times: 1010k] 1010k -> 1010k [Times: 1010k] 1010k -> 1010k [Times: 1010k] The user sys = = 0.00 0.00, Real =0.00 secs] [B@1b6d3586 [B@4554617c [B@74a14482 null NULL NULL NULL [B@6d6f6e28 [GC (Allocation Failure)) [PSYoungGen: 4694K->472K(5120K)] 17250K->13028K(18944K), 0.0011246 secs] [Times: The user sys = = 0.00 0.00, Real =0.00 secs] [B@1b6d3586 [B@4554617c [B@74a14482 null NULL NULL NULL null [B@135fbaa4 [GC (Allocation Failure) [PSYoungGen: 4657K->32K [PSYoungGen: 4657K->32K [PSYoungGen: 4657K->32K [PSYoungGen: 4657K->32K] User =0.00 sys=0.00, real=0.00 secs] [Full GC (Ergonomics) [PSYoungGen: 32K->0K(5632K)] 12980K->638K(13312K)] 13012K->638K(13312K), [Metaspace: 3232K->3232K(1056768K)], 0.0084781 secs] [Times: User =0.00 sys=0.00, real=0.01 secs] NULL NULL NULL NULL NULL NULL NULL NULL null null [B@45ee12a7 End of loop: 10 Heap PSYoungGen total 5632K, used 4371K [0x00000000ff980000, 0x0000000100000000, 0x0000000100000000) eden space 4608K, 94%, informs [x00000000ff980000 0, 0 x00000000ffdc4e70, 0 x00000000ffe00000) from space 1024 k, 0%, informs [x00000000fff00000 x00000000ffe00000 0, 0 x00000000ffe00000, 0) to space 1024 k, 0%, informs [x00000000fff00000 0, 0 x00000000fff00000, 0 x0000000100000000) ParOldGen total 7680 k, used 638K [0x00000000fec00000, 0x00000000ff380000, 0x00000000ff980000) object space 7680K, 8%, informs [x00000000fec00000 0, 0 x00000000fec9fa38, 0 x00000000ff380000) Metaspace informs the 3239 k, capacity 4500 k, committed 4864K, reserved 1056768K class space used 351K, capacity 388K, committed 512K, reserved 1048576KCopy the code

Phantom reference

A reference queue is associated when it is created

For example,

When ByteBuffer is created, a virtual reference object named Cleaner will be created. When ByteBuffer is not referenced by strong references, it will be garbage collected by JVM, and the virtual reference Cleaner will enter the reference queue, and a special thread will scan the reference queue. The direct memory address method is used to release the direct memory to ensure that the direct memory does not leak.

Application scenarios

Can be used to track the activity of objects being collected by the garbage collector, and a system notification is received before an object associated with a virtual reference is collected by the garbage collector.

The instance

Tracker(String path, FileDeleteStrategy deleteStrategy, Object marker,
   ReferenceQueue<? super Object> queue) {
    //marker is a concrete virtual reference object
    super(marker, queue);
    this.path = path;
    this.deleteStrategy = deleteStrategy == null ?    
    FileDeleteStrategy.NORMAL : deleteStrategy;
}

Copy the code

conclusion

Virtual reference is the weakest of all reference types. Whether an object has a virtual reference or not has no impact on its life cycle, and it cannot obtain an object instance through virtual reference. An object with a virtual reference is almost the same as an object without reference, and may be reclaimed by the garbage collector at any time. When you try to get a strong reference through the get() method of a virtual reference, you always fail. Furthermore, the virtual reference must be used with the reference queue to track the garbage collection process.

Finalizer reference

When the A4 object is not referenced by a strong reference, when the A4 object is garbage collected, the finalizer reference is put into a reference queue (the referenced object has not been garbage collected yet), with special threads (lower priority, The reference queue is scanned and the finallize() method is called to determine whether the reachable mechanism is still in place, and the referenced object is reclaimed only when GC is actually performed.

conclusion

  • Strong references: never recycled

  • Soft reference: It is reclaimed when memory runs out

  • Weak references: Collected during normal garbage collection

  • Virtual references: They are collected by the garbage collector at any time