Java provides four levels of reference: strong reference, soft reference, weak reference, and virtual referencejava.lang.refThere are concrete implementations under the package, and they are derived fromjava.lang.ref.Reference, as shown in the figure:

In addition to the weak virtual Reference, Reference also has a derived class Finalizer, which implements the finalize function.

🍦 ReferenceQueue🍦

Before the introduction of reference types, first to introduce a associated with all reference types are a dongdong: reference queue Java. Lang. Ref. ReferenceQueue.

ReferenceQueue can be used in combination with soft, weak and virtual references. Only the most important thing to know about ReferenceQueue is that the references that exist in ReferenceQueue refer to objects that have not been reclaimed by the JVM and are on their way to being reclaimed.

So what can RerferenceQueue do? Now that we know the most important thing, when the JVM retrieves objects, it sends a notification telling us that XX is collected, and we can also put finalize() to finalize things, but we’d better not do that!!

Let’s briefly mention the implementation of Finalize: Each object that is to be collected and contains Finalize () will be added to the FinalizeThread thread execution queue before being collected. This queue is called finencequeue. The object type in the queue is Finalizer. As can be seen from the UML class diagram above, Finalizer inherits from FinalReference. Each Finalizer wraps the objects to be collected, and then the elements in the queue queue to execute finalize function. Therefore, a bad Finalize function may cause objects to be referenced by Finalizer for a long time, which will accumulate in memory for a long time, which may cause OOM and further increase GC pressure

2. 🍫 strongly quoted 🍫

A strong reference is the type of reference commonly used in programs. Strongly referenced objects are touchable and cannot be reclaimed. Such as:

StringBuffer str = new StringBuffer("Strong Reference")
Copy the code

In the above code STR is a strong reference to the StringBuffer instance, where the STR local variable is allocated on the stack and the StringBuffer instance is allocated on the heap (or stack), if the following code is executed:

StringBuffer str2 = str;
Copy the code

Then the StringBuffer object instance has two references. So how can an object instance no longer have a strong reference? There is no reference to the instance:

str = null;
str2 = null;
Copy the code

Strong references have the following characteristics: 1) a strong reference can access the target object directly, 2) the object to which the strong reference refers will not be reclaimed by the system at any time, even in OOM 3) based on the second point, so strong references may cause memory leaks

3. 🍧 soft reference 🍧

Soft references corresponding implementation for Java. Lang. Ref. SoftReference, compared with strong reference is slightly a little bit weak, if when there is insufficient space on the heap memory, recycling soft reference object. As such, soft references can often be used for caching. Soft references can also be used in conjunction with the ReferenceQueue of the ReferenceQueue, and the JVM adds the soft reference to the ReferenceQueue associated with it if the object instance it points to is reclaimed.

Using JVM parameters-Xms7M -Xmx7m -XX:+PrintGCRun the following code

Results after operation:

In the sample program, the heap size is 7M and the PrintGC parameter is turned on to print the GC log when GC occurs. The following is divided into two parts:

The first part: in the main program, we first create a User object, hold a byte array of 4M size in the User object, consider the object instance size of 4M (certainly greater than 4M), and then create soft reference for the new User instance, remove the strong reference of the User object instance. After the system.gc () manual garbage collection is triggered, the contents of the User object instance can still be retrieved. The second part: followed by the first part, and then try again to allocate the size of the 4 m byte array, because we have only 7 m heap size, so this time affirmation cannot allocate, the system will trigger the GC, trigger GC, you can see about recovery from the recovery log 4 m space (that is, our soft reference objects), makes the new allocation of 4 m byte array can accommodate. And after that, the soft reference object gets NULL.

Conclusion: When GC occurs, soft-referenced objects are not necessarily recycled, except when memory resources are low, so soft-referenced objects do not cause memory leaks.

Application scenario: Cache

4, 🍨 weak quoted 🍨

Weak references are slightly weaker than soft references. When a system GC occurs, weak references are collected regardless of whether the system resources are sufficient at the time. Of course, the garbage collection thread usually has a low priority and does not necessarily find objects holding weak references in time. A weak reference corresponding implementation for Java. Lang. Ref. WeakReference. A weak reference can also be used in conjunction with the ReferenceQueue of the ReferenceQueue, and if the object instance to which the weak reference refers is reclaimed, the JVM adds the weak reference to the ReferenceQueue associated with it.

Using JVM parameters-Xms10M -Xmx10M -XX:+PrintGCRun the following code:You get the following input:From the output, we can see that after the manual force GC, there is an obvious reclaim of about 4M space, and the user we get is null, indicating that in the next GC, our weak reference object was reclaimed.

After looking at soft and weak references, you can see that both types of references are better suited for doing the optional caching. When the system runs out of memory, the cached data is reclaimed to provide more memory. When the system memory resources are sufficient, these cached data can exist for a considerable time.

Application scenario: 1) ThreadLocal resolves memory leaks

In a ThreadLocal first where the source code used to weak references: ThreadLocal. ThreadLocalMapEach thread will have a ThreadLocal ThreadLocalMap, ThreadLocalMap bottom is actually an array of Entry, the Entry of the key is the ThreadLocal, the value is the only accessible by the current thread object. Notice that this Entry inherits WeakReference, and the type represented by this WeakReference is the key of our Entry, that is, the ThreadLocal object. First of all, let’s assume that if we do not write as above, how can we design Entry?We could design it this way, and also achieve the goal of thread exclusivity, but what’s the problem with that? 1. We use ThreadLocal in our code to achieve thread exclusivity2, the implementation of Test1 Thread holds a ThreadLocal ThreadLocalMap 3, ThreadLocal. ThreadLocalMap Entry, Entry 4 ThreadLocal and Value 5. We ran out of Test1 and it was reclaimed by the JVM, meaning that the thread-exclusive data we created is no longer used

These are strong reference types, and some threads will not be destroyed immediately after being created. It may be that our system will die in the same month as it was born, which means that some ThreadLocal and saved values will not be used in the future, and then due to the existence of strong references, our memory will gradually burst, causing memory overflow.

Weak references are garbage collected regardless of resource availability. So if the Entry key is a weak reference, then the Entry key (ThreadLocal) will be reclaimed during GC, so you might ask, the entire Entry key is reclaimed, but the Value is still strongly referenced, still exists, still has a memory leak.

That’s right, so whenever you’re using a ThreadLocal, you should definitely suggest or check if there’s a place to remove this Entry from a ThreadLocal.

So somebody might say, well, since we need to show remove, right? Why make the key a weak reference?

Personally, I think this is a way of trying to get rid of the memory leaks, because there are always some careless programmer who forgets remove, right, or remove can never be called, and so on, and then using weak references will automatically recycle these unused objects, In addition, if the key of get, set, and remove of ThreadLocal is found to be null during the hash search, this Entry is invalid. In this case, ThreadLocal can guarantee to help us clean up this Entry.

2) WeakHashMap actually has the same idea as TheadLocal.

3) It can also be used for caching

5. 🍰 is quoted as 🍰

Virtual references are the weakest of the four reference types. If an object instance holds only virtual references, virtual reference objects can be collected by the garbage collector at any time, just as if there were no references. The realization of the virtual reference corresponding to Java. Lang. Ref. PhantomReference. Soft and weak references are used similarly, but virtual references are slightly different than other references:

1) Obtained by calling the get method with a virtual referenceIt’s always nullThat is, virtual application objects are alwaysunreachable, directly look at the source code:

2) there is only one constructor for a virtual reference and the virtual reference must be used in conjunction with a ReferenceQueue ReferenceQueue

Application scenario: 1) Reclaim out-of-heap memory

Beep Beep: It’s not clear what other scenarios this virtual reference could have