Brief introduction
First of all, you should know that Java has provided four reference types from 1.2, namely their references (strongreference), soft references (softreference), weak references (WeakReference), and Phantomreference ( Virtual references), they are ranked from large to small in the likelihood of GC recycling. Such as
You can see that reference is inherited from object, and there are three direct subclasses, that is, we are going to introduce several classes. There's another referencequeue, and I don't think anyone will know.
He was used to save a reference object that is about to be disposed, with the instance code below the specific user
Here is a separate introduction to each reference, and attached to the test code, to facilitate the deep understanding of everyone
Strongreference
Just like his name, any time the GC is not able to reclaim his, even if the memory is not enough, the system will directly throw an exception outofmemoryerror, will not be recycled, the first thing to say is that Java is the default is a strong reference, such as the following code:
new Persion();
where P is a strong reference and will not be recycled by GC at any time
/** * 测试强类型,可以看到我们调用多次gc他还是没有回收 */privatestaticvoidtestStrongReference() { new Person("Jack"); System.gc(); System.gc(); System.out.println(jack);}
SoftReference
Soft references his feature is that when memory is sufficient, objects of this reference type are not recycled, and are recycled only when there is insufficient memory, a feature that is best suited for most caches, such as the cache of images in Android
/** * 测试软类型引用 */privatestaticvoidtestSoftReference() { new Person("Jack"); new SoftReference<>(jack); System.out.println(personSoftReference.get()); null; System.gc(); System.gc(); System.out.println(personSoftReference.get());}
Output:
Person{name=‘Jack‘}Person{name=‘Jack‘}
You can see that although we have manually called the GC but the reference type has not been recycled
WeakReference
The feature of virtual references is that as long as the GC runs it will be recycled, and the personal feel is not much use, because as long as the GC runs he will be recycled '
privatestaticvoidtestWeakReference() { new Person("Jack"); new WeakReference<Person>(jack); System.out.println(personSoftReference.get()); System.gc(); System.gc(); System.out.println(personSoftReference.get());}
We run the code to find the object is still not recycled, because although we call the GC, this method only notifies him to execute, but what execution still depends on his mood. Of course, the above code has a very important reason is that the Jack object is a strong reference, so in how to invoke the GC he will not be recycled, why? Because Jack, the variable, he also strongly quoted the object, we gave him empty, in the call GC he was recycled, the following code:
privatestaticvoidtestWeakReference() { new Person("Jack"); new WeakReference<Person>(jack); System.out.println(personSoftReference.get()); null; System.gc(); System.gc(); System.out.println(personSoftReference.get());}
Output:
Person{name=‘Jack‘}null
We can see the results, as we expected.
Phantomreference
A virtual reference does not have a reference to it, primarily to create this type of reference, then the reference type is recycled
privatestaticvoidtestPhantomReference() { new Person("Jack"); new ReferenceQueue<>(); new PhantomReference<Person>(jack,personReferenceQueue); System.out.println(personSoftReference.get());// jack = null;// System.gc();// System.gc(); System.out.println(personSoftReference.get());}
Output:
nullnull
You can see that as soon as one is created, it is recycled directly.
Referencequeue
He is a reference to the column, you can monitor the reference object is 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:
privatestaticvoidtestReferenceQueue() { new Person("Jack"); new ReferenceQueue<>(); new WeakReference<Person>(jack, personReferenceQueue); null; System.gc(); System.out.println(personSoftReference.get());}
When the Jack object referenced by Personsoftreference is recycled, the system will add the Personsoftreference object to the Personreferencequeue, what exactly does it do, and imagine this scenario, A hashmap his key is a byte[] array, we need to create 10,000 such keys to add him to HashMap, which is if the machine's memory is small then he can be out of memory, but when we use a reference to wrap the key, Then add it to HashMap:
Private Static void testReferenceQueue1() {referencequeue<object> Weakreferencereferencequeue =NewReferencequeue<> ();intM1 =1024x768; Object o =NewObject (); map<weakreference<byte[]>, object> map =NewHashmap<> ();//Create a thread to listen for recycled objects NewThread (NewRunnable () {@Override Public void Run() {Try{intCNT =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 ()); } }Catch(Interruptedexception e) {//End Loop}}). Start (); for(inti =0; I <10000; i++) {byte[] bytes =New byte[M1]; Map.put (NewWeakreference<> (bytes,weakreferencereferencequeue), O); } System.GC (); System.out.println ("Map.size:"+ map.size ());}
Output:
...9997Recycle:java. Lang. Ref. WeakReference@2A62b5bc,nullmap.size:100009998Recycle:java. Lang. Ref. WeakReference@27E47833,nullmap.size:100009999Recycle:java. Lang. Ref. WeakReference@18E8473e,nullmap.size:10000
You can see that he recycles so many objects, because we return NULL when we call get (), but the problem is that the size of the map is still 10000, which is not what we expect, because the object that he refers to is looked back, and that map can be equivalent to a failure, What we want is to recycle the reference object, which means that the size of map becomes the size of the actual available object.
Private Static void testReferenceQueue2() {referencequeue<object> Weakreferencereferencequeue =NewReferencequeue<> ();intM1 =1024x768; Object o =NewObject (); map<weakreference<byte[]>, object> map =NewHashmap<> ();//Create a thread to listen for recycled objects NewThread (NewRunnable () {@Override Public void Run() {Try{intCNT =0; weakreference<byte[]> K; while((k = (weakreference) weakreferencereferencequeue.remove ())! =NULL) {Map.Remove (k);//Here we remove references to recycled objectsSystem.out.println ((cnt++) +"Recycle:"+ k); System.out.println ("Map.size:"+ map.size ()); } }Catch(Interruptedexception e) {//End Loop}}). Start (); for(inti =0; I <10000; i++) {byte[] bytes =New byte[M1]; Map.put (NewWeakreference<> (bytes, weakreferencereferencequeue), O); } System.GC (); System.out.println ("Map.size:"+ map.size ());}
Output:
9996Recycle:java. Lang. Ref. WeakReference@1608Bcbdmap.size:39997Recycle:java. Lang. Ref. WeakReference@777C9dc9map.size:29998Recycle:java. Lang. Ref. WeakReference@535779E4map.size:19999Recycle:java. Lang. Ref. WeakReference@6F6745d6map.size:0
You can see the object that was recycled, and we removed its key from the map.
Weakhashmap
His effect is similar to the above, when a key reference object is recycled, he will automatically remove the key
We loaded the list with even values in the table below so that he wouldn't be allowed to recycle those objects.
Private Static void Testweakhashmap() {referencequeue<object> Weakreferencereferencequeue =NewReferencequeue<> ();intM1 =1024x768; Object o =NewObject (); map<byte[], object> map =NewWeakhashmap<> (); arraylist<byte[]> bytes1 =NewArraylist<> (); for(inti =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 the recovered key.
Reference: http://www.iflym.com/index.php/java-programe/201407140001.html
Deep understanding of 4 types of reference in Java