finalize () and Reflections four kinds of references

Think on ThreadLocal learning initiated

ThreadLocal for Entry of reference is a weak reference, so think of the life cycle or four references.

  1. Strong reference, not for garbage collection
  2. Soft references, JVM memory is not enough, for recycling
  3. Weak reference, the next GC, direct recycling
  4. Virtual reference, does not have any impact on the GC, ReferenceQueue used in combination, when notified only recovered reference.

So if there is only a weak reference pointing ThreadLocal, then the next GC, ThreadLocal will be recycled. Ali ThreadLocal code specification also requires modifications to be static, but also is to prevent subsequent use, but ThreadLocal has been recovered GC.

To test the weak reference is then GC wrote the following code:

    @Test
    public void test() throws InterruptedException {
        ReferenceQueue queue = new ReferenceQueue();

        Thread thread = new Thread(() -> {
            while (true){
                Object obj;
                if((obj = queue.poll())!= null){
                        System.out.println("queue!!! " + obj);
                }
            }
        });

        thread.start();
        Reference reference1 = new Reference();
        WeakReference reference = new WeakReference(reference1, queue);
        System.out.println(reference);
        reference1 = null;

        System.gc();

        thread.join();

    }

    private static class Reference {

        @Override
        protected void finalize() throws Throwable {
            System.out.println("finalize!!!"+this);
        }
    }

Output is as follows:

java.lang.ref.WeakReference@200a570f
queue!!! java.lang.ref.WeakReference@200a570f
finalize!!!ConnectionTest$Reference@74560fd0

output queue than finalize before, I thought it was io competition, ignore ignore the weak reference instead phantom reference, then the output is:

java.lang.ref.PhantomReference@200a570f
finalize!!!ConnectionTest$Reference@74560fd0

output queue has not, then I suspect that my code issue, then someone else on the Internet Baidu's example changed, the normal output queue, I suspect the problem is my custom class, so the original code is replaced by a virtual reference String

PhantomReference reference = new PhantomReference(new String(), queue);

Normal output, what? ? ? But my custom class Nothing ah, only a finalize (), would it affect the references, but no problem weak references, phantom references have a problem? ? ? So I changed the phantom reference soft references, then create a large array of normal output.

So I suspect finalize have any effect on virtual reference, can find a bug, I Baidu and finalize a virtual reference, and then locate the following articles:

JAVA virtual reference Why not be placed in the queue referenced in the recovery after the heavy load finalize?

execution finalize method

Details can be seen: How the Handle to the Java Finalization's Memory-Retention Issues

  1. When overriding the finalize () of class instantiation, JVM will mark the object as finalizable
  2. GC thread when an object is detected unreachable, if the object is finalizable, adds the object to the finalization queue, subject to re-up, delayed GC
  3. finalizer thread after some time, the team will be the finalization queue object, calls the finalize (), then mark the object is finalized
  4. GC thread again object is detected unreachable, then recovered objects.

See also understand this virtual reference after rewriting the finalize () Why does the output queue, to go through two GC, objects will be recovered, then before entering Reference Queue, code changes are as follows:

    @Test
    public void test5() throws InterruptedException {
        Reference reference = new Reference();
        ReferenceQueue referenceQueue = new ReferenceQueue();
        Thread thread = new Thread(() -> {
            while (true){
                Object obj;
                if((obj = referenceQueue.poll())!= null){
                    System.out.println("queue!!! "+obj);
                }
            }
        });

        thread.start();
        PhantomReference reference1 = new PhantomReference(reference, referenceQueue);
        reference = null;
        System.gc();
        Thread.sleep(1000);
        System.gc();
        thread.join();
    }

Output is as follows:

finalize!!!ConnectionTest$Reference@74560fd0
queue!!! java.lang.ref.PhantomReference@5b708109

jstat can also see differences were analyzed by GC twice:

Gc output queue is not the case:

Gc output queue of the case:

1569746263537

Virtual and weak references into the Reference Queue opportunity

As already explained the reasons why no references virtual output queue, but why only after one weak references to gc output of the queue? ?

JAVA virtual reference Why not be placed in the queue referenced in the recovery after the heavy load finalize?

Weak reference phantom reference, finalize practice, their order, and

These two articles mentioned:

  1. Weak references: Once the object has only weak references, GC will be weak references directly into the reference queue, and insert finalization queue is the same timing.
  2. False quote: To officially be recovered in the object, before entering the reference queue

In addition, I also found jdk8 clear referent phantom reference objects without calling clear (), in reference to the queue manually cleared.

jdk8 PhantomReference comments as follows:

* Unlike soft and weak references, phantom references are not
* automatically cleared by the garbage collector as they are enqueued.  An
* object that is reachable via phantom references will remain so until all
* such references are cleared or themselves become unreachable.

Guess you like

Origin www.cnblogs.com/wuweishuo/p/11609652.html