Java reference type

Source: Internet
Author: User
Tags java reference

Java reference type

When the blogger recently sorted out the Java Collection framework and sorted out WeakHashMap, he felt it necessary to elaborate on the Java reference type first. Therefore, I would like to give you more comments on this article.
If you don't talk much about it, go directly to the topic. Java provides four levels of references: strong application, soft reference, weak reference, and virtual reference. The four references are defined under the java. lang. ref package.

Final Reference)

It is common in program code, such as Object obj = new Object (). As long as a strong reference still exists, the garbage collector will never recycle the referenced Object.
Strong references have three features:

1. Strong references can directly access the target object; 2. Objects pointed to by strong reference locks will not be recycled by the system at any time. JVM would rather throw an OOM exception than reclaim the objects pointed to by strong references. 3. Strong applications may cause memory leakage;

The definition of the entire FinalReference class is as follows (Some APIs do not include descriptions of the FinalReference class and can only look at the source code ):

package java.lang.ref;/* Final references, used to implement finalization */class FinalReference
  
    extends Reference
   
     {    public FinalReference(T referent, ReferenceQueue
     q) {        super(referent, q);    }}
   
  

It can be seen from the class definition that there is only one constructor that constructs a strong reference based on the application and application queue of the given object.

Soft Reference)

Is used to describe some useful but not necessary objects. For soft reference associated objects, these objects will be listed in the recycle range for the second recycle before the system will encounter a memory overflow exception. If the recovery does not have enough memory, a memory overflow exception will be thrown.
For soft reference associated objects, if the memory is sufficient, the garbage collector will not recycle the object. If the memory is insufficient, the memory of these objects will be recycled. After JDK 1.2, the SoftReference class is provided for soft reference. Soft references can be used to implement memory-sensitive high-speed cache. Soft references can be used together with a ReferenceQueue. If the referenced objects are recycled by the garbage collector, the Java virtual machine adds this soft reference to the reference queue associated with it.
Case 1:

Package collections. ref; import java. lang. ref. Reference; import java. lang. ref. ReferenceQueue; import java. lang. ref. SoftReference; public class SoftRefTest {private static ReferenceQueue
  
   
SoftQueue = new ReferenceQueue <> (); public static class MyObject {@ Override protected void finalize () throws Throwable {super. finalize (); System. out. println ("MyObject's finalize called") ;}@ Override public String toString () {return "I am MyObject" ;}} public static class CheckRefQueue implements Runnable {Reference
   
    
Obj = null; @ Override public void run () {try {obj = (Reference
    
     
) SoftQueue. remove ();} catch (InterruptedException e) {e. printStackTrace ();} if (obj! = Null) {System. out. println ("Object for SoftReference is" + obj. get () ;}} public static void main (String [] args) {MyObject object = new MyObject (); SoftReference
     
      
SoftRef = new SoftReference <> (object, softQueue); new Thread (new CheckRefQueue ()). start (); object = null; // delete a strongly referenced System. gc (); System. out. println ("After GC: Soft Get =" + softRef. get (); System. out. println ("allocating large memory"); byte [] B = new byte [5*1024*928]; System. out. println ("After new byte []: Soft Get =" + softRef. get (); System. gc ();}}
     
    
   
  

Run parameter 1:

-Xmx5M

Result 1:

After GC: Soft Get = I am MyObject allocate large memory MyObject's finalize calledObject for SoftReference is nullAfter new byte []: Soft Get = null

Run parameter 2:

-Xmx5M -XX:PrintGCDetails

Result 2:

[GC [PSYoungGen: 680 K-> 504 K (2560 K)] 680 K-> 512 K (6144 K), 0.0040658 secs] [Times: user = 0.00 sys = 0.00, real = 0.00 secs] [Full GC [PSYoungGen: 504 K-> 0 K (2560 K)] [ParOldGen: 8 K-> 482 K (3584 K)] 512 K-> 482 K (6144 K) [PSPermGen: 2491 K-> 2490 K (21504 K)], 0.0188479 secs] [Times: user = 0.01 sys = 0.00, real = 0.02 secs] After GC: Soft Get = I am MyObject allocating large blocks of memory [GC [PSYoungGen: 123 K-> 64 K (2560 K)] 605 K-> 546 K (7680 K), 0.0004285 secs] [Times: user = 0.00 sys = 0.00, real = 0.00 secs] [GC [PSYoungGen: 64 K-> 64 K (2560 K)] 546 K-> 546 K (7680 K), 0.0003019 secs] [Times: user = 0.00 sys = 0.00, real = 0.00 secs] [Full GC [PSYoungGen: 64 K-> 0 K (2560 K)] [ParOldGen: 482 K-> 482 K (4608 K)] 546 K-> 482 K (7168 K) [PSPermGen: 2493 K-> 2493 K (21504 K)], 0.0094748 secs] [Times: user = 0.02 sys = 0.00, real = 0.01 secs] [GC [PSYoungGen: 0 K-> 0 K (2560 K)] 482 K-> 482 K (7680 K), 0.0003759 secs] [Times: user = 0.00 sys = 0.00, real = 0.00 secs] [Full GC [PSYoungGen: 0 K-> 0 K (2560 K)] [ParOldGen: 482 K-> 472 K (5120 K)] 482 K-> 472 K (7680 K) [PSPermGen: 2493 K-> 2493 K (21504 K)], 0.0101017 secs] [Times: user = 0.06 sys = 0.00, real = 0.01 secs] MyObject's finalize calledObject for SoftReference is nullAfter new byte []: soft Get = null [GC [PSYoungGen: 122 K-> 32 K (2560 K)] 5235 K-> 5144 K (7680 K), 0.0004806 secs] [Times: user = 0.00 sys = 0.00, real = 0.00 secs] [Full GC [PSYoungGen: 32 K-> 0 K (2560 K)] [ParOldGen: 5112 K-> 5112 K (5120 K)] 5144 K-> 5112 K (7680 K) [PSPermGen: 2493 K-> 2493 K (21504 K)], 0.0136270 secs] [Times: user = 0.06 sys = 0.00, real = 0.01 secs] Heap PSYoungGen total 2560 K, used 20 K [0x000000000000ffd00000, 0x0000000100000000, 0x0000000100000000) eden space 2048 K, 1% used [0x00000000ffd00000, clerk, 0x000000000000fff00000) from space 512 K, 0% used [clerk, clerk, 0x00000000fff80000) to space 512 K, 0% used [0x000000000000fff80000, clerk, 0x0000000100000000) ParOldGen total 5120 K, used 5112 K [0x000000000000ff800000, 0x00000000ffd00000, 0000) object space 5120 K, 99% used [0x00000000ff800000, 0000, 0x000000000000ffd00000) PSPermGen total 21504 K, used 2500 K [0x000000000000fa600000, 0x000000000000fbb00000, 0x000000000000ff800000) object space 21504 K, 11% used [0x000000000000fa600000, 0x0000fa871190, 0x000000000000fbb00000)

Add-XX: run the PrintGCDetails parameter to view details about GC collection.
In Case 1, first construct a MyObject object and assign it to the object variable to form a strong reference. Then, use SoftReference to construct the soft reference softRef of this MyObject object and register it with the softQueue reference queue. When softRef is recycled, it is added to the softQueue queue. If obj = null is set, this strong reference is deleted. Therefore, only soft references are left for MyObject object references in the system. In this case, GC is called and the soft-referenced get () method is used to obtain the reference of the MyObject object. It is found that the object is not recycled. This indicates that GC is in sufficient memory, soft reference objects are not recycled.
Next, request a large heap space of 5*1024*928. This operation will make the system heap memory usage tight and generate a new round of GC. After this GC, softRef. get () does not return the MyObject object, but returns null, indicating that soft references are recycled when the system memory is insufficient. When soft reference is recycled, it is added to the registered reference queue.
If you increase the value of the array in the above case, for example, 5*1024*1024, an OOM exception will be thrown:

After GC: Soft Get = I am MyObject allocate large memory MyObject's finalize calledObject for SoftReference is nullException in thread "main" java. lang. outOfMemoryError: Java heap space at collections. ref. softRefTest. main (SoftRefTest. java: 58)

Soft reference is mainly used in memory-sensitive high-speed cache, which is often used in android systems. Generally, Android apps use a large number of default images, which are used in many places. If you read an image each time, hardware operations are required to read the file, resulting in low performance. Therefore, we want to cache the image and read it directly from the memory when necessary. However, because the image occupies a large amount of memory and many images need a lot of memory to cache, The OutOfMemory exception may easily occur. At this time, we can consider using soft reference technology to avoid this problem. SoftReference can solve the oom problem. Every object is instantiated through soft reference, and this object is saved as a cache. When this object is called again, you can obtain the resource data in the object by using the get () method in the soft reference. In this way, you do not need to read the data again, but you can directly read the data from the cache, when OOM occurs in the memory, GC will immediately clear all soft references to prevent oom.
Case 2:

Public class BitMapManager {private Map
  
   
> ImageCache = new HashMap
   
    
> (); // Save the soft reference of Bitmap to HashMap public void saveBitmapToCache (String path) {// Bitmap object with strong reference Bitmap bitmap = BitmapFactory. decodeFile (path); // soft referenced Bitmap object SoftReference
    
     
SoftBitmap = new SoftReference
     
      
(Bitmap); // Add the object to Map to cache imageCache. put (path, softBitmap); // after use, manually set the bitmap object to null Bitmap = null;} public bitmap getBitmapByPath (String path) {// obtain the soft referenced Bitmap object SoftReference from the cache
      
        SoftBitmap = imageCache. get (path); // determines whether soft reference if (softBitmap = null) {return null;} // retrieves a Bitmap object. if Bitmap is recycled due to insufficient memory, an empty Bitmap bitmap = softBitmap will be obtained. get (); return bitmap ;}}
      
     
    
   
  
Weak Reference)

It is used to describe non-essential objects, but its strength is weaker than soft references. objects associated with weak references can only survive until the next spam request is sent. When the spam collector is working, only objects associated with weak references will be reclaimed no matter whether the current memory is sufficient. Once a weak reference object is recycled by the garbage collector, it is added to a registration reference queue.
Let's slightly modify the code of Case 1 as follows:

Package collections. ref; import java. lang. ref. Reference; import java. lang. ref. ReferenceQueue; import java. lang. ref. WeakReference; public class WeakRefTest {private static ReferenceQueue
  
   
WeakQueue = new ReferenceQueue <> (); public static class MyObject {@ Override protected void finalize () throws Throwable {super. finalize (); System. out. println ("MyObject's finalize called") ;}@ Override public String toString () {return "I am MyObject" ;}} public static class CheckRefQueue implements Runnable {Reference
   
    
Obj = null; @ Override public void run () {try {obj = (Reference
    
     
) WeakQueue. remove ();} catch (InterruptedException e) {e. printStackTrace ();} if (obj! = Null) {System. out. println ("the deleted weak reference is:" + obj + "but get the weak reference object obj. get () = "+ obj. get () ;}} public static void main (String [] args) {MyObject object = new MyObject (); Reference
     
      
WeakRef = new WeakReference <> (object, weakQueue); System. out. println ("the weak reference created is:" + weakRef); new Thread (new CheckRefQueue ()). start (); object = null; System. out. println ("Before GC: Weak Get =" + weakRef. get (); System. gc (); System. out. println ("After GC: Weak Get =" + weakRef. get ());}}
     
    
   
  

Running results without parameters:

The Weak reference created is: [email protected] Before GC: Weak Get = I am MyObjectAfter GC: Weak Get = nullMyObject's finalize called. The Weak reference deleted is: [email protected] but obtains the weak referenced object obj. get () = null

We can see that, before GC, the weak reference object is not found by the garbage collector. Therefore, the corresponding object reference can be obtained through weakRef. get. But as long as the garbage collection,Weak references are immediately recycled once discoveredAnd add it to the registration reference queue. Attempt to get the object reference through weakRef. get () will fail.
For detailed examples of weak references, refer to WeakHashMap. The bloggers will sort out relevant documents in the near future. Friends who can't wait can spend their time on their own.

Both soft reference and weak reference are suitable for storing cache data that is dispensable. If this is done, when the system memory is insufficient, the cached data will be recycled without causing memory overflow. When the memory resources are sufficient, the cached data can take a long time to accelerate the system.

Phantom Reference)

A Virtual Reference is also called a ghost reference or phantom reference. It is the weakest reference relationship. An object holding a Virtual Reference is almost the same as a non-referenced object, and may be recycled by the garbage collector at any time. When you try to use the get () method of Virtual Reference to obtain a strong reference, it will always fail. In addition, the virtual reference must be used with the reference queue to track the garbage collection process.
The implementation of the get method in the Virtual Reference is as follows:

    public T get() {        return null;    }

Null is always returned.
Let's modify the code of Case 1:

Package collections. ref; import java. lang. ref. phantomReference; import java. lang. ref. reference; import java. lang. ref. referenceQueue; import java. util. concurrent. timeUnit; public class PhantomRefTest {private static ReferenceQueue
  
   
PhanQueue = new ReferenceQueue <> (); public static class MyObject {@ Override protected void finalize () throws Throwable {super. finalize (); System. out. println ("MyObject's finalize called") ;}@ Override public String toString () {return "I am MyObject" ;}} public static class CheckRefQueue implements Runnable {Reference
   
    
Obj = null; @ Override public void run () {try {obj = (Reference
    
     
) PhanQueue. remove (); System. out. println ("the deleted Virtual Reference is:" + obj + "but the object that obtains the Virtual Reference obj. get () = "+ obj. get (); System. exit (0);} catch (InterruptedException e) {e. printStackTrace () ;}} public static void main (String [] args) throws InterruptedException {MyObject object = new MyObject (); Reference
     
      
PhanRef = new PhantomReference <> (object, phanQueue); System. out. println ("the created Virtual Reference is:" + phanRef); new Thread (new CheckRefQueue ()). start (); object = null; TimeUnit. SECONDS. sleep (1); int I = 1; while (true) {System. out. println ("+" + I ++ "gc"); System. gc (); TimeUnit. SECONDS. sleep (1 );}}}
     
    
   
  

Running result:

The created Virtual Reference is: [email protected] 1st gcMyObject's finalize called 2nd gc Delete Virtual Reference: [email protected] but get virtual reference object obj. get () = null

As you can see, after GC again, the system finds the garbage object and calls the finalize () method to reclaim the memory, but does not immediately join the recycle queue. In the second GC, the object is actually clearly identified by GC. In this case, it is added to the Virtual Reference queue.
The biggest role of Virtual Reference is to recycle the tracking object and clear related resources of the destroyed object.
When an object is not used, the finalize method of the class that loads the object can reclaim the object Resources. However, if you accidentally use the finalize method, the object will be revived. For example, you can write the finalize method as follows:

public class Test{    public static Test obj;    @Override protected void finalize() throws Throwable{        super.finalize();        obj = this;    }}

In the preceding Test class, obj = new Test (); obj = null; then, System is called. gc () tries to destroy the object, but sorry, no matter how many times you call the System. gc () is useless, unless you get obj = null in the following code; in this way, the object can be recycled, this is because JVM only executes the overwritten finalize method for an object once at most.
The above small snippets show that the method of rewriting finalize is not very reliable. You can use virtual quotes to clear the resources occupied by objects.
The following code is used:

Public class PhantomRefTest2 {private static ReferenceQueue
  
   
PhanQueue = new ReferenceQueue <> (); private static Map
   
    
, String> map = new HashMap <> (); public static class MyObject {@ Override protected void finalize () throws Throwable {super. finalize (); System. out. println ("MyObject's finalize called") ;}@ Override public String toString () {return "I am MyObject" ;}} public static class CheckRefQueue implements Runnable {Reference
    
     
Obj = null; @ Override public void run () {try {obj = (Reference
     
      
) PhanQueue. remove (); Object value = map. get (obj); System. out. println ("clean resource:" + value); map. remove (obj); System. out. println ("the deleted Virtual Reference is:" + obj + "but the object that obtains the Virtual Reference obj. get () = "+ obj. get (); System. exit (0);} catch (InterruptedException e) {e. printStackTrace () ;}} public static void main (String [] args) throws InterruptedException {MyObject object = new MyObject (); Reference
      
        PhanRef = new PhantomReference <> (object, phanQueue); System. out. println ("the created Virtual Reference is:" + phanRef); new Thread (new CheckRefQueue ()). start (); map. put (phanRef, "Some Resources"); object = null; TimeUnit. SECONDS. sleep (1); int I = 1; while (true) {System. out. println ("+" + I ++ "gc"); System. gc (); TimeUnit. SECONDS. sleep (1 );}}}
      
     
    
   
  

Running result:

The created Virtual Reference is: [email protected] 1st times gcMyObject's finalize called 2nd times gcclean resource: Some Resources the deleted Virtual Reference is: [email protected] but obtains the virtual referenced object obj. get () = null

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.