2020 let's talk about four quotations of "strong weakness and emptiness"

Keywords: Programming Java jvm

In the past, when learning strong weak virtual reference, I just looked at the blog and didn't write my own code to practice and prove it. As a result, I forgot it after reading it every time. Later, I made up my mind to knock on the code by myself, so that I could be more impressed. The ancients said that I had to feel shallow on the paper and never knew that I had to do it.

Four references in Java

There are four reference types in Java: strong reference, soft reference, weak reference and virtual reference.

Why Java should design these four kinds of references

Java's memory allocation and memory recycling do not need the responsibility of the programmer. They are all the responsibility of the great JVM. Whether an object can be recycled depends on whether there is a reference to the object. The professional point is called reachability analysis.

Java designs these four references for two main purposes:

The programmer can determine the life cycle of an object by means of code;

There is recycling.

Strong citation

Strong reference has no actual corresponding type in java.lang.ref, but 99.9999% of the code we write in our program is strong reference:

Object o = new Object();

This is a strong reference, is it everywhere in the code, the most cordial.

As long as an object has a strong reference associated with it, the object will never be recycled. Even if there is insufficient memory, the JVM would rather throw an OOM than recycle it.

So when can it be recycled? When the association between a strong reference and an object is broken, it can be recycled.

We can manually associate the interrupt, and the method is particularly simple:

o = null;

We can call GC manually to see whether resources will be recycled if the association between strong references and objects is interrupted. In order to observe the recycling more conveniently and clearly, we need to write a new class, and then rewrite the finalize method. Let's do this experiment:

public classStudent{    @Override    protectedvoidfinalize()throwsThrowable{        System.out.println("Student It's been recycled.");    }}
publicstaticvoidmain(String[] args){        Student student = new Student();        student = null;        System.gc();}

Operation result:

Student is recycled

It is clear that the resources have been recycled.

Of course, in actual development, never rewrite the finalize method

In the actual development, we can see that some objects are manually assigned to NULL, which is probably to "specially remind" the JVM that this resource can be garbage collected.

Strong citation has the following characteristics:

Strong references can directly access the target object

Objects pointed to by strong references (existence) will not be recycled at any time, and the JVM would rather throw an OOM exception than recycle.

Strong references can cause memory leaks

Note: in order to avoid memory shortage, we can set the variable sb to null after the variable sb is used to speed up object recycling.

Explanation: 1. Out of memory refers to that when a program applies for memory, there is not enough memory space for it to use, and out of memory appears

Memory leak refers to that after a program applies for memory, it is unable to release the memory space that has been applied for. Such a leak will add up to many, and memory leak will lead to out of memory

Soft reference

Let's first see how to create a soft reference:

SoftReferencestudentSoftReference=new SoftReference(new Student());

Soft reference is to wrap objects with soft reference. When we need to get wrapped objects from soft reference objects, we just need to get them:

SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());        Student student = studentSoftReference.get();        System.out.println(student);

What are the characteristics of soft citation

When there is insufficient memory, the JVM's GC will be triggered. If there is still insufficient memory after GC, the wrapped object of the soft reference will be killed. That is to say, the JVM will recycle the object only when there is insufficient memory.

It's still the same. We have to do experiments to deepen our impression:

SoftReference<byte[]> softReference = new SoftReference<byte[]>(new byte[1024*1024*10]);        System.out.println(softReference.get());        System.gc();        System.out.println(softReference.get());        byte[] bytes = new byte[1024 * 1024 * 10];        System.out.println(softReference.get());

I defined a soft reference object, in which byte [] is wrapped, and byte [] occupies 10M, and then 10Mbyte [] is created.

To run the program, you need to bring a parameter:

-Xmx20M

Represents the maximum heap memory of 20 m.

Operation result:

[B@11d7fff[B@11d7fffnull

It is clear that the byte [] wrapped by the soft reference object is still alive after GC is completed manually. However, when we create a 10M byte [], the maximum heap memory is not enough, so we kill the byte [] wrapped by the soft reference object. If we don't, we will throw OOM.

What is the use of soft reference? It is more suitable for caching. When the memory is enough, you can get the cache normally. When the memory is not enough, you will kill the cache first and not throw OOM immediately.

The soft reference can also be used with a reference queue. If the object (obj) in the soft reference is recycled, the soft reference will be added to the associated reference queue by the JVM.

ReferenceQueue<Object> queue = new ReferenceQueue<>();Object obj = new Object();SoftReference softRef = new SoftReference<Object>(obj,queue);//Delete strong reference obj = null; / / call gcsystem. Gc(); system. Out. Println("gc After value: " + softRef.get()); // Object still exists / / apply for large memory to make the memory space utilization reach the threshold value, and force gcbyte[] bytes = new byte[100 * 1024 * 1024]; / / if obj is recycled, the soft reference will enter the reference queue reference <? > reference = queue. Remove();if (reference != null){    System.out.println("Object has been recycled: "+ reference.get());  // Object is null}

Reference queue function

The meaning of queue is that we can monitor the references in the queue externally. When the objects in the references are recycled, we can continue to clean up the reference objects themselves, because our reference objects (softRef) also occupy certain resources.

Weak reference

The use of weak reference is similar to that of soft reference, except that the keyword becomes WeakReference:

WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1024*1024*10]);        System.out.println(weakReference.get());

The feature of weak reference is that no matter whether the memory is enough or not, as long as GC occurs, it will be recycled:

WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1]);        System.out.println(weakReference.get());        System.gc();        System.out.println(weakReference.get());

Operation result:

[B@11d7fffnull

It is clear that there is enough memory, but when GC is triggered, the resource is recycled.

Weak references are useful in many places, such as ThreadLocal and WeakHashMap.

Weak references can also be used with a reference queue. If the object (obj) in the weak reference is recycled, the soft reference will be added to the associated reference queue by the JVM.

ReferenceQueue<Object> queue = new ReferenceQueue<>();Object obj = new Object();WeakReference weakRef = new WeakReference<Object>(obj,queue);//Remove strong reference obj = null; system.out.println("gc After value: " + weakRef.get()); // Object still exists / / call gcSystem.gc(); / / if obj is recycled, the soft reference will enter the reference queue reference <? > reference = queue. Remove();if (reference != null){    System.out.println("Object has been recycled: "+ reference.get());  // Object is null}

Both soft reference and weak reference are very suitable for storing the optional cache data. When the memory is insufficient, the cache data will be recycled (and then queried through alternative schemes). When the memory is sufficient, the cache data can also exist for a long time to accelerate.

application

WeakHashMap

When the key has only weak references, GC will automatically clean up the key and value after discovery, as a simple cache table solution.

ThreadLocal

ThreadLocal.ThreadLocalMap.Entry inherits the weak reference. The key is the current thread instance, which is basically the same as WeakHashMap.

Virtual reference

Virtual reference is also called phantom reference. Let's see its use:

ReferenceQueue queue = new ReferenceQueue();        PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);        System.out.println(reference.get());

The use of virtual reference is quite different from the soft reference and weak reference mentioned above. We can run ReferenceQueue directly no matter what it is

null

Unexpectedly, null is printed out. Let's see the source code of get method:

publicTget(){        return null;    }

This means that null is returned directly.

This is one of the characteristics of virtual reference: virtual reference cannot be used to obtain the real reference to an object.

What is the meaning of the existence of virtual reference? This is going back to the code above us. We need to copy the code to prevent you from turning up again:

ReferenceQueue queue = new ReferenceQueue();        PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);        System.out.println(reference.get());

To create a virtual reference object, in addition to passing in the wrapped object, we also passed in a ReferenceQueue, which can be seen from its name as a queue.

The second feature of virtual reference is that virtual reference must be used with ReferenceQueue. When GC is ready to recycle an object, if it finds that it has virtual reference, it will add the virtual reference to the ReferenceQueue associated with it before recycling.

Let's practice with code:

ReferenceQueue queue = new ReferenceQueue();        List<byte[]> bytes = new ArrayList<>();        PhantomReference<Student> reference = new PhantomReference<Student>(new Student(),queue);        new Thread(() -> {            for (int i = 0; i < 100;i++ ) {                bytes.add(new byte[1024 * 1024]);            }        }).start();        new Thread(() -> {            while (true) {                Reference poll = queue.poll();                if (poll != null) {                    System.out.println("Virtual references are recycled:" + poll);                }            }        }).start();        Scanner scanner = new Scanner(System.in);        scanner.hasNext();    }

Operation result:

Student is recycled virtual reference is recycled: java.lang.ref.PhantomReference@1ade6f1

We simply analyze the following code:

The first thread plugs data into the collection. With more and more data, GC will happen.

The second thread is in a dead cycle. Take the data from the queue. If the data is not null, print it.

From the running results, we can see that when GC occurs, virtual references will be recycled, and the recycled notifications will be put into ReferenceQueue.

What's the use of virtual references? In NIO, virtual reference is used to manage out of heap memory.

All of the above are my own thoughts. You are welcome to share them. By the way, please pay attention to them. Partners who have problems or need to learn materials can click Java learning exchange group Let's talk

 

Posted by Burns on Mon, 09 Mar 2020 03:22:18 -0700