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<WEAKREFERENCE<BYTE[]>, 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<WEAKREFERENCE<BYTE[]>, 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