An important feature of the Java language is the introduction of an automatic memory management mechanism that allows developers to manage memory in their applications without their own. C + + developers need to explicitly allocate and free memory through functions such as Malloc/free and New/delete. This puts a high demand on developers, which can cause problems such as memory access errors and memory leaks. A common problem is the "hanging reference" (dangling references), where an object reference points to a memory chunk that has been incorrectly reclaimed and reassigned to a new object, which can cause unpredictable results if the program continues to use the reference. It is possible for a developer to forget to explicitly call a function that frees memory, causing a memory leak. Automatic memory management is the task of the management of memory to the programming language of the operating environment to complete. Developers do not need to be concerned with the underlying details of memory allocation and recycling. The Java platform uses the garbage collector for automatic memory management.
Java garbage collection mechanism
The Java garbage collector is responsible for completing 3 tasks: allocating memory, ensuring that the referenced object's memory is not being reclaimed incorrectly, and reclaiming the memory space of objects that are no longer referenced. Garbage collection is a complex and time-consuming operation. If the JVM spends too much time on garbage collection, it will inevitably affect the running performance of the application. In general, when the garbage collector is in the recycling operation, the execution of the entire application is temporarily aborted (Stop-the-world). This is because the garbage collector needs to update the actual memory address referenced by all objects in the app. Different hardware platforms can support different ways of garbage collection. For example, on a multi-CPU platform, you can recycle garbage in a parallel way. The single CPU platform can only be serialized. The garbage collection methods that are expected by different applications will also vary. Server-side apps may want to spend the entire run time of the app, the smaller the total amount of time spent on garbage collection, the better. For applications that interact with the user, you may want to have a smaller time interval for the application that the garbage collection brings. In this case, a variety of garbage collection methods and corresponding performance tuning parameters are available in the JVM, and the application can be customized as needed.
The most basic approach to the Java garbage collection mechanism is generational recycling. The in-memory area is divided into generations, and the objects are stored in the corresponding generation region according to their time of survival. The general implementation is divided into 3 generations: young, old and permanent. The allocation of memory is occurring in the young generation. When an object survives long enough, it is copied into the old age. Different garbage collection algorithms can be used for different generations. The starting point for generational division is the statistical Law of the study of the survival time of the object in application. In general, most objects in an application have a very short survival time. For example, the survival time of local variables is only in the process of executing the method. Based on this, the garbage collection algorithm for younger generations can be very targeted.
The memory area of the young generation is further divided into the Eden and two surviving areas (survivor space). Eden is the place where memory is allocated, a contiguous area of free memory. Memory allocations on top are very fast because there is no need to make available blocks of memory for lookups. There is always a blank in the two surviving zones. In the garbage collection, the Garden of Eden and the surviving objects in one of the non-empty surviving areas are copied to the current empty surviving or old age according to their survival time. After this copy, the previously non-empty surviving area contains the currently surviving objects, while the Eden and the contents of the other surviving area are no longer needed, simply emptying the two areas. The roles of the two surviving areas were exchanged during the next garbage collection. In general, the younger generation region is smaller, and most of the objects are no longer alive, so it is more efficient to find the surviving objects in them.
For the memory areas of old and permanent generations, a different recycling algorithm is used, called "Mark-purge-compress (mark-sweep-compact)". The process of marking is to find out the object that is still alive and mark it, and clear to traverse the whole memory area to find the area where it needs to be reclaimed, while compression moves the memory of the surviving object to one end of the whole memory area, so that the other end is a contiguous idle area, which facilitates memory allocation and replication.
4 different garbage collection mechanisms are available in JDK 5. The most common is the serial recovery method, which uses a single CPU to reclaim the memory of young and old generations. During the recycling process, the application is temporarily aborted. The recycling method uses the most basic generational recycling mentioned above. The serial recycling method is suitable for the general single CPU desktop platform. If it is a multi-CPU platform, then it is suitable for the parallel recycling method. In this way, when a young generation is recycled, multiple CPUs are used for parallel processing to improve the performance of recycling. Concurrency Token-clear recycling is appropriate for applications that require a high response time requirement to reduce the time it takes for the application to be temporarily aborted by garbage collection. The advantage of this approach is that you can tag live objects and recycle garbage while the app is running, and only temporarily abort the application for a short time.
The jconsole provided in the JDK makes it easy to see the memory usage of the current app. Add parameter-VERBOSE:GC when the JVM is started to see the results of the garbage collector running.
Java reference types
If an in-memory object does not have any references, it means that the object is no longer being used and can be a candidate for garbage collection. However, since the runtime of the garbage collector is uncertain, the actual collection time of objects that can be garbage collected is indeterminate. For an object, it persists in memory as long as there is a reference. If such objects become more and more, exceeding the total amount of memory in the JVM, the JVM throws a outofmemory error. While the specific operation of garbage collection is controlled by the JVM, developers can still interact with the garbage collector to a certain extent, with the aim of helping the garbage collector manage the memory of the application in a better way. This interaction is the JAVA.LANG.REF package introduced with JDK 1.2.
Strong references
In a generic Java program, the most visible is a strong reference (strong reference). As Date date = new Date (), date is a strong reference to an object. A strong reference to an object can be passed around in a program. In many cases, multiple references are directed at the same object. The presence of a strong reference limits the time that an object survives in memory. If object A contains a strong reference to object B, then in general, the lifetime of object B will not be shorter than object A. If object A does not explicitly set the reference to object B to null, only if object A is garbage collected, and object B no longer has a reference to it, the opportunity to be garbage collected may be obtained.
In addition to strong references, the JAVA.LANG.REF package provides a different way to refer to an object. The JVM's garbage collector has different ways of handling different types of references.
Soft references
Soft references (soft reference) are weaker than strong references in strength and are represented by class SoftReference. Its role is to tell the garbage collector which objects in the program are less important and can be temporarily reclaimed when the memory is low. When there is not enough memory in the JVM, the garbage collector releases objects that are only pointed to by soft references. If all of these objects are released, the memory is not enough to throw a outofmemory error. Soft references are ideal for creating caches. When the system is running out of memory, the contents of the cache can be freed. Consider an image editor program, for example. The program will read the entire contents of the image file into memory for easy processing. Users can also open multiple files at the same time. When too many files are open at the same time, it can cause insufficient memory. If a soft reference is used to point to the contents of the image file, the garbage collector can reclaim the memory when necessary.
1 Public classImageData {2 PrivateString Path;3 Privatesoftreference<byte[]>Dataref;4 PublicImageData (String path) {5 This. Path =path;6Dataref =Newsoftreference<byte[]> (New byte[0]);7 }8 Private byte[] Readimage () {9 return New byte[1024 * 1024];//The operation to read a file is omittedTen } One Public byte[] GetData () { A byte[] DataArray =dataref.get (); - if(DataArray = =NULL|| Dataarray.length = = 0) { -DataArray =readimage (); theDataref =Newsoftreference<byte[]>(DataArray); - } - returnDataArray; - } +}
When running the above program, you can use the-XMX parameter to limit the memory available to the JVM. Because the object that the soft reference points to may be reclaimed, it is always checked to see if the object is still alive when it is used to get the object that the soft reference is actually pointing to by the Get method.
Weak references
Weak references (weak reference) are weaker than soft references in strength and are represented by class WeakReference. It does this by referencing an object, but does not prevent the object from being recycled. If a strong reference is used, the referenced object cannot be reclaimed as long as the reference exists. Weak references do not have this problem. When the garbage collector runs, the object is recycled if all references to an object are weak references. The function of weak references is to solve the coupling relationship between objects brought by strong references in the time of survival. The most common use of weak references is in a collection class, especially in a hash table. The interface of a hash table allows any Java object to be used as a key. When a key-value pair is placed into a hash table, the Hashtable object itself has a reference to those keys and value objects. If such a reference is a strong reference, the hash table object itself will not be recycled as long as it is alive. If a long-lived hash table contains many key-value pairs, it can eventually consume all of the memory in the JVM.
The solution to this situation is to use weak references to refer to these objects so that key and value objects in the hash table can be garbage collected. Weakhashmap is available in Java to meet this common need.
Ghost Citation
Before introducing ghost references, you should first describe the object termination mechanism (finalization) provided by Java. There is a Finalize method in the object class, which is designed to perform some cleanup work before an object is actually recycled. Because Java does not provide a mechanism similar to that of C + + destructors, it is implemented by the Finalize method. But the problem is that the garbage collector's run time is not fixed, so the actual running time of these cleanup work is unpredictable. Ghost references (phantom Reference) can solve this problem. You must specify a reference queue when creating a ghost reference phantomreference. When an object's Finalize method has been called, the Ghost reference to the object is added to the queue. By checking the contents of the queue, you know whether an object is ready to be recycled.
Ghost references and their queues are rarely used, and are used primarily to achieve more granular memory usage control, which is significant for mobile devices. The program can then request memory to create a new object after the object is determined to be recycled. In this way, the memory consumed by the program is kept to a relatively low number. For example, the following code gives a sample implementation of a buffer.
1 Public classPhantombuffer {2 Private byte[] data =New byte[0];3 Privatereferencequeue<byte[]> queue =Newreferencequeue<byte[]>();4 Privatephantomreference<byte[]> ref =Newphantomreference<byte[]>(data, queue);5 Public byte[] Get (intsize) {6 if(Size <= 0) {7 Throw NewIllegalArgumentException ("Wrong buffer size");8 }9 if(Data.length <size) {Tendata =NULL; OneSystem.GC ();//force the garbage collector to run A Try { -Queue.remove ();//the method blocks until the queue is not empty -Ref.clear ();//Ghost references are not automatically emptied, to be run manually theref =NULL; -data =New byte[size]; -ref =Newphantomreference<byte[]>(data, queue); -}Catch(interruptedexception e) { + e.printstacktrace (); - } + } A returndata; at } -}
In the preceding code, each time a new buffer is requested, it is first ensured that the byte array of the previous buffer has been successfully reclaimed. The Remove method of the reference queue is blocked until a new ghost reference is added to the queue. However, it is important to note that this practice can cause the garbage collector to run too many times, which can cause the program to be too low in throughput.
Reference queue
In some cases, the program will need to be notified when an object's accessibility has changed. For example, a strong reference to an object no longer exists, leaving only soft or weak references. But there is also a need to do some processing on the reference itself. A typical scenario is in a hash table. The reference object is the key object in the Weakhashmap, and when the actual object it references is garbage collected, it is necessary to remove the key value pair from the hash table. With the reference queue (Referencequeue), you can easily get these weakly referenced objects and remove them from the table. References to actual objects are automatically emptied when soft references and weak reference objects are added to the queue. Reference objects in the queue can be obtained in a non-blocking and blocking manner, respectively, by referencing the Poll/remove method of the queue.
Resources
- Java Memory Management Whitepaper
- Tuning Garbage Collection with the 5.0 JAVA[TM] Virtual machine
- Plugging memory leaks with soft references
- Plugging memory leaks with weak references
Java garbage collection mechanism reference types