In versions earlier than JDK, when an object is not referenced by any variable, the program will no longer be able to use this object. That is to say, the program can use the object only when it is reachable. This is like in daily life, after buying an item from a store, if it is useful, keep it; otherwise, it will be thrown into the garbage bin and taken away by the cleaners. Generally, if an item has been thrown into a garbage bin, it is impossible to pick it up and use it again.
However, sometimes the situation is not that simple, and you may encounter items similar to chicken ribs. This kind of item is useless now. It will take up space to keep it, but it is not worthwhile to discard it immediately because it may be useful in the future. A compromise solution for such dispensable items is: if the Home Space is sufficient, keep it at home first. If the home space is insufficient, even if all the household items are cleared, they still cannot accommodate the essential necessities, and then they are discarded.
Since jdk1.2, the object reference is divided into four levels, so that the program can control the object lifecycle more flexibly. The four levels are from high to low: strong reference, soft reference, weak reference, and virtual reference.
1. Strong reference
The references mentioned above in this chapter are actually strong references, which are the most common references. If an object has a strong reference, it is similar to an essential necessities. The Garbage Collector will never recycle it. When the memory space is insufficient, the Java Virtual Machine would rather throw an outofmemoryerror to terminate the program abnormally and does not recycle strongly referenced objects to solve the problem of insufficient memory.
2. Soft reference)
If an object only has soft references, it is similar to the necessities that can be used. If the memory space is sufficient, the garbage collector will not recycle it. If the memory space is insufficient, the memory of these objects will be recycled. The object can be used by programs as long as the garbage collector does not recycle it. Soft references can be used to implement memory-sensitive high-speed cache.
Soft references can be used together with a referencequeue, the Java virtual machine adds this soft reference to the reference queue associated with it.
3. weakreference)
If an object only has weak references, it is similar to a necessities that can be used. The difference between weak references and soft references is that only objects with weak references have a shorter life cycle. When the Garbage Collector thread scans the memory area under its jurisdiction, its memory will be recycled no matter whether the current memory space is sufficient or not. However, since the garbage collector is a thread with a low priority, it may not soon find objects with weak references.
Weak references can be used together with a referencequeue, the Java virtual machine adds this weak reference to the reference queue associated with it.
4. phantomreference)
As the name implies, "virtual references" are just the same as virtual ones, which are different from other types of references. Virtual references do not determine the object lifecycle. If an object only holds a virtual reference, it is the same as no reference and may be recycled at any time.
Virtual references are mainly used to track the activity of objects being reclaimed by garbage collection. A difference between virtual and soft references and weak references is that virtual references must be used together with the reference Queue (referencequeue. When the zookeeper recycler is about to recycle an object, if it finds that it has a virtual reference, it will add this virtual reference to the reference queue associated with it before it recycles the object's memory. The program can know whether the referenced queue is added with virtual references.
Whether the referenced object is to be recycled. If the program finds that a virtual reference has been added to the reference queue, it can take necessary action before the memory of the referenced object is recycled.
In this book, "Reference" can be either a verb or a noun. Readers should distinguish the meaning of "Reference" based on context.
The Java. Lang. Ref package provides three classes: softreference class, weakreference class, And phantomreference class, which represent soft reference, weak reference, and virtual reference respectively. The referencequeue class indicates the reference queue. It can be used with these three reference classes to track the collection of referenced objects by the Java Virtual Machine. The following program creates a String object, referencequeue object, and weakreference object:
// Create a strong reference
String STR = new string ("hello ");
// Create a reference queue. <string> indicates the reference of the string object in the queue.
Referencequeue <string> RQ = new referencequeue <string> ();
// Create a weak reference that references the "hello" object and is associated with the RQ reference queue
// <String> it is a fan mark, indicating that weakreference will weakly reference the string object
Weakreference <string> WF = new weakreference <string> (STR, rq );
After the above code is executed, the relationship between the reference and the object in the memory is 11-10.
Figure 11-10 "hello" objects have both strong references and weak references
In Figure 11-10, arrows with solid lines represent strong references, and arrows with dotted lines represent weak references. It can be seen that the "hello" object is strongly referenced by STR and weak referenced by a weakreference object. Therefore, the "hello" object will not be recycled.
In the following program code, set the STR variable that references the "hello" object to null, and then obtain the reference of the "hello" object through the weakreference weak reference get () method:
String STR = new string ("hello"); // ①
Referencequeue <string> RQ = new referencequeue <string> (); // ②
Weakreference <string> WF = new weakreference <string> (STR, rq); // ③
STR = NULL; // ④ cancel the strong reference of the "hello" Object
String str1 = WF. Get (); // ⑤ if the "hello" object is not recycled, str1 references the "hello" Object
// If the "hello" object is not recycled, RQ. Poll () returns NULL.
Reference <? Extends string> ref = RQ. Poll (); // 6
After executing the fourth row above, the relationship between the reference and the object in the memory is shown in 11-11. At this time, the "hello" object only has weak references, so it may be garbage collection. If the object has not been recycled, the WF. Get () method in row ⑤ will return a reference to the "hello" object and make the object highly referenced by str1. Then, when the RQ. Poll () method is executed in Row 6, null is returned because no reference is provided in the reference queue. The poll () method of referencequeue is used to return the reference in the queue. If not, null is returned.
Figure 11-11 "hello" objects only have weak references
In the following program code, after executing line 4, the "hello" object only has weak references. The next two calls the system. GC () method to urge the Garbage Collector to work, thus improving the possibility that the "hello" object will be recycled. If the "hello" object is recycled, the reference of the weakreference object is added to the referencequeue, and then WF. the get () method returns NULL, and RQ. the poll () method returns the reference of the weakreference object. Figure 11-12 shows the relationship between the reference in the memory and the object after the execution of the nth row.
String STR = new string ("hello"); // ①
Referencequeue <string> RQ = new referencequeue <string> (); // ②
Weakreference <string> WF = new weakreference <string> (STR, rq); // ③
STR = NULL; // ④
// Push the Garbage Collector twice to improve the possibility of "hello" objects being recycled
System. GC (); // ⑤
System. GC (); // ⑥
String str1 = WF. Get (); // 7 if the "hello" object is recycled, str1 is null
Reference <? Extends string> ref = RQ. Poll (); // returns
Figure 11-12 The "hello" object is garbage collected and weak references are added to the reference queue.
In the references class of the following routine from 11 to 15, 10 soft references, 10 weak references, and 10 virtual references are created in sequence. Each of them references a grocery object. It can be seen from the printed results of the program running that the Virtual Reference is the same as the virtual setting. The referenced objects may be garbage collected at any time, and objects with weak references have a long life cycle, when the Garbage Collector executes the garbage collection operation, some objects that can be recycled and soft-referenced objects have a long life cycle. However, when the Java Virtual Machine considers that the memory is insufficient, it will also be recycled.
Routine 11-15 references. Java
Import java. Lang. Ref .*;
Import java. util .*;
Class grocery {
Private Static final int size = 10000;
// Attribute D makes each grocery object occupy a large amount of memory, with a size of about 80 KB
Private double [] d = new double [size];
Private string ID;
Public grocery (string ID) {This. ID = ID ;}
Public String tostring () {return ID ;}
Public void finalize (){
System. Out. println ("finalizing" + id );
}
}
Public class references {
Private Static referencequeue <grocery> RQ = new referencequeue <grocery> ();
Public static void checkqueue (){
Reference <? Extends grocery> INQ = RQ. Poll (); // retrieve a reference from the queue
If (INQ! = NULL)
System. Out. println ("in queue:" + INQ + ":" + INQ. Get ());
}
Public static void main (string [] ARGs ){
Final int size = 10;
// Create 10 grocery objects and 10 soft references
Set <softreference <grocery> SA = new hashset <softreference <grocery> ();
For (INT I = 0; I <size; I ++ ){
Softreference <grocery> ref =
New softreference <grocery> (new grocery ("soft" + I), rq );
System. Out. println ("just created:" + ref. Get ());
SA. Add (REF );
}
System. GC ();
Checkqueue ();
// Create 10 grocery objects and 10 weak references
Set <weakreference <grocery> WA = new hashset <weakreference <grocery> ();
For (INT I = 0; I <size; I ++ ){
Weakreference <grocery> ref =
New weakreference <grocery> (new grocery ("weak" + I), rq );
System. Out. println ("just created:" + ref. Get ());
Wa. Add (REF );
}
System. GC ();
Checkqueue ();
// Create 10 grocery objects and 10 virtual references
Set <phantomreference <grocery> Pa = new hashset <phantomreference <grocery> ();
For (INT I = 0; I <size; I ++ ){
Phantomreference <grocery> ref =
New phantomreference <grocery> (new grocery ("phantom" + I), rq );
System. Out. println ("just created:" + ref. Get ());
Pa. Add (REF );
}
System. GC ();
Checkqueue ();
}
}
There is a special map type in the Java Collection: weakhashmap, which stores weak references to key objects. When a key object is reclaimed, then the reference of the corresponding value object will be deleted from the map. Weakhashmap can save storage space and cache non-essential data. For the general usage of the map interface, see section 15th (MAP) in Chapter 1 of this book ).
The main () method of the mapcache class of the 11-16 routine creates a weakhashmap object, which stores weak references of a group of key objects, and the main () method also creates an array object, it stores strong references to some key objects.
Routine 11-16 mapcache. Java
Import java. util .*;
Import java. Lang. Ref .*;
Class key {
String ID;
Public Key (string ID) {This. ID = ID ;}
Public String tostring () {return ID ;}
Public int hashcode (){
Return ID. hashcode ();
}
Public Boolean equals (Object R ){
Return (r instanceof key)
& Amp; id. Equals (key) R). Id );
}
Public void finalize (){
System. Out. println ("finalizing key" + id );
}
}
Class value {
String ID;
Public value (string ID) {This. ID = ID ;}
Public String tostring () {return ID ;}
Public void finalize (){
System. Out. println ("finalizing value" + id );
}
}
Public class mapcache {
Public static void main (string [] ARGs) throws exception {
Int size = 1000;
// Or obtain the size from the command line
If (ARGs. length> 0) size = integer. parseint (ARGs [0]);
Key [] keys = new key [size]; // stores strong references to key objects
Weakhashmap <key, value> whm = new weakhashmap <key, value> ();
For (INT I = 0; I <size; I ++ ){
Key K = new key (integer. tostring (I ));
Value v = new value (integer. tostring (I ));
If (I % 3 = 0) Keys [I] = K; // make the key object hold a strong reference
Whm. Put (K, V); // make the key object hold weak references
}
// Urge the Garbage Collector to work
System. GC ();
// Give the CPU to the garbage collector thread
Thread. Sleep (8000 );
}
}
The printed results of the above program are as follows:
Finalizing key 998.
Finalizing key 997.
Finalizing key 995.
Finalizing key 994.
Finalizing key 992.
Finalizing key 991.
Finalizing key 989.
Finalizing key 988.
Finalizing key 986.
Finalizing key 985.
Finalizing key 983.
The printed result shows that after the system. GC () method is executed, the garbage collector only recycles key objects that only hold weak references. The ID can be strongly referenced by the key object of an integer of 3, so it is not recycled.