Deep understanding of 4 types of reference Java __java

Source: Internet
Author: User
Brief Introduction

First, you should all know that Java provides four reference types from 1.2, namely their references (strongreference), soft references (softreference), weak references (WeakReference), and Phantomreference ( Virtual references), they are likely to be retrieved from large to small in GC. The following figure

You can see that reference is inherited from object, and there are three direct subclasses, that is, we want to introduce a few classes. There's also a referencequeue I don't think everyone knows.

He was used to save the reference object that is about to be released, the user has the following instance code

Here is a separate introduction to each reference, and the test code to facilitate the in-depth understanding of strongreference

Can be his name, any time GC is not able to recycle him, even if the memory is not enough, the system will throw an exception outofmemoryerror, will not be recycled, first of all to explain that Java is the default is strong reference, such as the following code:

Persion p = new Persion ();

where P is a strong reference and will not be collected at any time by GC

/**
 * Test strong type, you can see we call multiple GC He's still not recycled
 * * *
private static void Teststrongreference () {person
    jack = new Man ("Jack");
    System.GC ();
    System.GC ();
    System.out.println (Jack);
SoftReference

Soft references his feature is that when memory is sufficient it does not recycle objects of this type of reference, but is recycled only when there is not enough memory, which is ideal for caching of images in Android.

/**
 * Test soft type reference
/private static void Testsoftreference () {person
    jack = new Person ("Jack");
    softreference<person> personsoftreference = new softreference<> (jack);
    System.out.println (Personsoftreference.get ());
    Jack = null;
    System.GC ();
    System.GC ();
    System.out.println (Personsoftreference.get ());
}

Output:

Person{name= ' Jack '}
person{name= ' Jack '}

You can see that although we called the GC manually, the reference type is not recycled weakreference

The characteristic of a virtual reference is that it will be recycled as soon as the GC runs, and the individual feels less useful, because as soon as the GC is run, he will be recycled.

private static void Testweakreference () {person
    jack = new Person ("Jack");
    weakreference<person> personsoftreference = new weakreference<person> (jack);
    System.out.println (Personsoftreference.get ());
    System.GC ();
    System.GC ();
    System.out.println (Personsoftreference.get ());
}

We run the code to find that the object is still not recycled, because although we call GC, this method only notifies him of execution, but what execution still depends on his mood. Of course the above code has a very important reason is that Jack object He is a strong reference, so in how to call GC He will not be recycled, why. Because jack this variable he is also strong reference to the object, we give him empty, in the call GC he was recycled, the following code:

private static void Testweakreference () {person
    jack = new Person ("Jack");
    weakreference<person> personsoftreference = new weakreference<person> (jack);
    System.out.println (Personsoftreference.get ());
    Jack = null;
    System.GC ();
    System.GC ();
    System.out.println (Personsoftreference.get ());
}

Output:

Person{name= ' Jack '}
null

can see the result as we expected phantomreference

A virtual reference is not referenced as a reference, primarily to create this type of reference, then the type that he refers to reclaims the

private static void Testphantomreference () {person
    jack = new Person ("Jack");
    referencequeue<person> personreferencequeue = new referencequeue<> ();
    phantomreference<person> personsoftreference = new Phantomreference<person> (jack,personReferenceQueue) ;
    System.out.println (Personsoftreference.get ());        jack = null;        System.GC ();        System.GC ();
    System.out.println (Personsoftreference.get ());
}

Output:

NULL
NULL

You can see that once you've created it, you're going to recycle it directly referencequeue

He is a reference to the column, can monitor the reference object being recycled, specifically when a reference object he refers to the value is recycled, then the system will add this reference to the column, the following code:

private static void Testreferencequeue () {person
    jack = new Person ("Jack");
    referencequeue<person> personreferencequeue = new referencequeue<> ();
    weakreference<person> personsoftreference = new Weakreference<person> (Jack, personreferencequeue);
    Jack = null;
    System.GC ();
    System.out.println (Personsoftreference.get ());
}

When Personsoftreference's reference to the Jack object is recycled, the system will add personsoftreference objects to the Personreferencequeue, what is the role of the specific, imagine this scenario, A hashmap his key is an byte[] array, we need to create 10,000 such keys to add him to the HashMap, which is that if the machine's memory is small then he can run out of memory, but when we wrap the key with a reference, And then when you add to HashMap, you don't:

private static void TestReferenceQueue1 () {referencequeue<object> weakreferencereferencequeue = new referencequ

    Eue<> ();
    int M1 = 1024;
    Object o = new Object ();

    MAP&LT;WEAKREFERENCE&LT;BYTE[]&GT, object> map = new hashmap<> ();
                Create a thread to listen for recycled objects new thread (new Runnable () {@Override public void run () {try {
                int cnt = 0;
                Weakreference<byte[]> K;  while ((k = (weakreference) weakreferencereferencequeue.remove ())!= null) {System.out.println (cnt++)
                    + "Recycle:" + K + "," +k.get ());
                System.out.println ("map.size:" + map.size ());

    The catch (Interruptedexception e) {//End Loop}}}). Start ();
        for (int i = 0; I < 10000 i++) {byte[] bytes = new BYTE[M1];
    Map.put (New weakreference<> (bytes,weakreferencereferencequeue), O); } System. GC (); System.out.println ("map.size:" + map.size ());}

Output:

...
9997recycle:java.lang.ref.weakreference@2a62b5bc,null
map.size:10000
9998recycle: Java.lang.ref.weakreference@27e47833,null
map.size:10000
9999recycle:java.lang.ref.weakreference@ 18e8473e,null
map.size:10000

You can see he's recycled so many objects, because we return NULL when we call Get (), the problem is that the size of the map is still 10000, which is not what we expected because the object he is referencing is being looked back on, and that the map can be equivalent to failure, What we want is to recycle the reference object, meaning that the size of the map becomes the size of the real available object.

private static void TestReferenceQueue2 () {referencequeue<object> weakreferencereferencequeue = new referencequ

    Eue<> ();
    int M1 = 1024;
    Object o = new Object ();

    MAP&LT;WEAKREFERENCE&LT;BYTE[]&GT, object> map = new hashmap<> ();
                Create a thread to listen for recycled objects new thread (new Runnable () {@Override public void run () {try {
                int cnt = 0;
                Weakreference<byte[]> K; while ((k = (weakreference) weakreferencereferencequeue.remove ())!= null) {map.remove (k);//Here we remove the
                    Recycle object's Reference System.out.println ((cnt++) + "Recycle:" + K);
                System.out.println ("map.size:" + map.size ());

    The catch (Interruptedexception e) {//End Loop}}}). Start ();
        for (int i = 0; I < 10000 i++) {byte[] bytes = new BYTE[M1]; Map.put (New weakreference<> (bytes, weakReferencereferencequeue), O);
    } System.GC (); System.out.println ("map.size:" + map.size ());}

Output:

9996RECYCLE:JAVA.LANG.REF.WEAKREFERENCE@1608BCBD
map.size:3
9997recycle:java.lang.ref.weakreference@ 777C9DC9
map.size:2
9998recycle:java.lang.ref.weakreference@535779e4
map.size:1
9999recycle: Java.lang.ref.weakreference@6f6745d6
map.size:0

We can see the retrieved object, and we remove its key from the map weakhashmap

His effect is similar to the above, when a key reference object is recycled, he will automatically remove this key

We loaded the list with an even number of the following table so that he wouldn't be allowed to recycle the objects.

private static void Testweakhashmap () {
    referencequeue<object> weakreferencereferencequeue = new Referencequeue<> ();

    int M1 = 1024;
    Object o = new Object ();
    Map<byte[], object> map = new weakhashmap<> ();

    arraylist<byte[]> bytes1 = new arraylist<> ();
    for (int i = 0; I < 10000 i++) {
        byte[] bytes = new BYTE[M1];
        if (i%2==0) {
            bytes1.add (bytes);
        }
        Map.put (bytes, o);
        Bytes  = null;
    }
    System.GC ();
    System.out.println ("map.size:" + map.size ());
}

Output:

map.size:5000

You can see that as we said above, he will remove which keys are recycled.

Reference: http://www.iflym.com/index.php/java-programe/201407140001.html

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.