Understanding and solving of Java memory leaks

Source: Internet
Author: User
Tags object object java reference

Java Memory Management mechanism

In the C + + language, if you need to allocate a chunk of memory dynamically, programmers need to be responsible for the entire life cycle of this memory. From the application assignment, to the use, to the final release. The process is very flexible, but cumbersome, and the programmer is prone to inadvertently forget to release memory, resulting in memory leaks. The Java language has made its own optimizations for memory management, which is the garbage collection mechanism. Almost all memory objects in Java are allocated on heap memory (except for the base data type), and the GC (garbage Collection) is responsible for automatically reclaiming memory that is no longer in use.

Above is the basic situation of the Java Memory management mechanism. But if we just understand this, we will still encounter memory leaks in the actual project development. Perhaps some people doubt that, since the Java garbage collection mechanism can automatically reclaim memory, how can there be a memory leak situation? This problem, we need to know when the GC reclaims memory objects, what kind of memory objects will be considered by the GC is "no longer used".

Access to memory objects in Java, using a reference method. In Java code We maintain a reference variable of a memory object, and through the value of the reference variable, we can access the memory object space in the corresponding memory address. In a Java program, the reference variable itself can be stored in heap memory and placed in the memory of the code stack (the same as the basic data type). GC threads start tracking from reference variables in the code stack to determine which memory is being used. If the GC thread is unable to trace a chunk of memory in this way, then the GC will assume that the memory is no longer in use (because the memory is inaccessible in the code).

With this graph-based approach to memory management, a GC can recycle a memory object after it loses all references. Conversely, if the object still has a reference, it will not be recycled by GC, even if the Java virtual machine throws OutOfMemoryError.

Java memory leaks

There are generally two kinds of memory leaks. A situation such as in the C + + language, the allocated memory in the heap, when it is not released, all the way to access the memory is deleted (such as pointer re-assignment), and the other is that the memory object is clearly not needed, still retains the memory and its access (reference). The first case, in Java has been due to the introduction of garbage collection mechanism, has been well resolved. So, the memory leak in Java, mainly refers to the second case.

Perhaps the concept of light is too abstract, you can look at this example:

1 vector v=new vector (10);
2 for (int i=1;i<100; i++) {
3 Object O=new object ();
4 V.add (o);
5 O=null;
6}

In this example, there is a reference to the vector object in the code stack with reference to the V and object o. In the For loop, we constantly generate new objects, add them to the vector object, and then empty the O reference. The question is, if a GC occurs when the O reference is empty, can we create an object that is recycled by GC? The answer is in the negative. Because, when the GC traces a reference in the code stack, it discovers a V reference, and continues to trace, it finds that the memory space pointed to by the V reference has a reference to the object. This means that although the O reference is already empty, there are still other references to object objects that can be accessed, so the GC cannot release it. If after this loop the object object has no effect on the program, we assume that the Java program has a memory leak.

Despite the small amount of damage caused by a Java memory leak in the case of memory leaks in C + +, in most cases the program will still run normally, except in the rare case of a program crash. However, when mobile devices have tighter limits on both memory and CPU, Java's memory overflow can lead to inefficient programs and high memory consumption. This will cause the entire machine

In general cases where complex data structures are not involved, Java's memory leaks behave as a memory object whose lifetime exceeds the length of time the program needs it. We also sometimes call it "object Free".

For example:

1 public class filesearch{
2
3 private byte[] content;
4 private File Mfile;
5
6 Public filesearch (file file) {
7 Mfile = file;
8}
9
Ten public boolean hasstring (String str) {
one int size = GetFileSize (mfile);
Content = new Byte[size];
LoadFile (mfile, content);
14
The string s = new string (content);
return S.contains (str);
17}
18}

In this code, there is a function hasstring in the FileSearch class to determine whether the document contains the specified string. The process is to load the mfile into memory first and then make a judgment. However, the problem here is that the content is declared in order to be an instance variable, not a local variable. Then, after this function returns, there is still data for the entire file in memory. It is clear that the data we follow is no longer needed, which creates an unwarranted waste of memory.

To avoid a memory leak in this case, we need to manage our own allocated memory in C + + memory management thinking. The first is to clarify the valid scope of the memory object before declaring the object reference. A memory object that is valid within a function should be declared as a local variable, the same as the life cycle of the class instance, to be declared as an instance variable ... And so on Second, when the memory object is no longer needed, remember to manually empty its reference.

Memory leak problems in complex data structures

In actual projects, we often use some more complex data structures to cache the information needed for the program to run. Sometimes, because the data structure is too complex, or we have some special needs (for example, in case of memory permitting, as much as possible to cache information to improve the speed of the program, etc.), it is difficult for us to define the life cycle of data structure. At this point, we can use a special mechanism in Java to prevent memory leaks.

As we have described before, the GC mechanism of Java is built on the reference mechanism for tracking memory. And before that, the references we used all just defined an "Object o;" Such a form. In fact, this is just one of the default cases in the Java reference mechanism, and there are other ways to refer to it. By using these special reference mechanisms, together with the GC mechanism, we can achieve some of the effects we need.

Several ways of referencing in Java

There are several different ways of referencing in Java: Strong, soft, weak, and virtual. Below, we begin with a detailed understanding of the implications of these kinds of citation methods.
Strong references

The references we used earlier in this article were strong references, which are the most common references. If an object has a strong reference, it is similar to essential necessities, and the garbage collector will never recycle it. When there is not enough memory space, the Java virtual Machine prefers to throw a outofmemoryerror error, which causes the program to terminate abnormally, and does not rely on random recycling of strongly referenced objects to resolve out-of-memory issues.

Soft references (SoftReference)

A typical use of the SoftReference class is for memory-sensitive caches. The principle of softreference is to ensure that all soft references are purged before the JVM reports an out-of-memory condition while maintaining a reference to the object. The key is that the garbage collector may (and may not) release soft-and-accessible objects at run time. Whether an object is disposed depends on the algorithm of the garbage collector and the amount of memory available when the garbage collector is running.

Weak references (WeakReference)

A typical use of the WeakReference class is normalized mapping (canonicalized mapping). In addition, weak references are useful for objects that have a relatively long lifetime and are not expensive to recreate. The key is that when the garbage collector runs, if it encounters a weakly accessible object, the object referenced by WeakReference is freed. Note, however, that the garbage collector may have to run multiple times to find and release a weak and accessible object.

Virtual Reference (Phantomreference)

The Phantomreference class can only be used to track the upcoming collection of referenced objects. Again, it can be used to perform pre-mortem cleanup operations. Phantomreference must be used with the Referencequeue class. Referencequeue is required because it can act as a notification mechanism. When the garbage collector determines that an object is a virtual object, the Phantomreference object is placed on its referencequeue. Placing the Phantomreference object on Referencequeue is also a notification that the object referenced by the Phantomreference object has ended and is ready for collection. This allows you to take action just before the memory that the object occupies is recycled. Reference is used in conjunction with Referencequeue.

The interaction of GC, reference and Referencequeue

A, the GC cannot delete the memory of an object that has a strong reference.

B, GC found a soft reference to the object memory, then:

The referent field of the ①softreference object is set to NULL, so that the object no longer references the heap object.

The heap object referenced by ②softreference is declared as finalizable.

③ when the Finalize () method of the heap object is run and the memory occupied by the object is freed, the SoftReference object is added to its referencequeue (if the latter exists).

C, the GC discovers an object memory with only a weak reference, then:

The referent field of the ①weakreference object is set to NULL, so that the object no longer references the heap object.

The heap object referenced by ②weakreference is declared as finalizable.

③ when the Finalize () method of the heap object is run and the memory occupied by the object is freed, the WeakReference object is added to its referencequeue (if the latter exists).

D, the GC discovers an object memory with only a virtual reference, then:

The heap object referenced by ①phantomreference is declared as finalizable.

②phantomreference is added to its referencequeue before the heap object is freed.

Notable places include the following:

1, GC in general will not find soft-referenced memory objects, only when the memory is clearly insufficient to discover and release the soft reference object memory.

2, the GC discovery and release of weak references is not immediately, sometimes need to repeat several times GC, only to find and release the weak reference memory objects.
3, soft reference and weak reference when added to Referencequeue, its reference to the real memory has been set to empty, the associated memory has been released. While the virtual reference is added to the Referencequeue, the memory is not released and can still be accessed.

code example

Through the above introduction, I believe you have the reference mechanism of Java and several references to the similarities and differences already have a certain understanding. The concept of light, which may be too abstract, follows an example of how to use the reference mechanism in code.

1 String str = new string ("Hello"); ①
2 referencequeue<string> RQ = new referencequeue<string> (); Ii
3 weakreference<string> wf = new weakreference<string> (str, RQ); ③
4 Str=null; ④ to cancel a strong reference to the "Hello" object
5 String str1=wf.get (); ⑤ if the "Hello" object is not recycled, str1 references the "Hello" object
6//If the "Hello" object is not reclaimed, rq.poll () returns null
7 reference<? Extends string> ref=rq.poll (); ⑥

In the above code, note ⑤⑥ two places. If the "Hello" object is not reclaimed Wf.get () returns a "Hello" string object, Rq.poll () returns NULL, and the "Hello" object has been reclaimed, then Wf.get () returns Null,rq.poll () Returns the Reference object, but there is no reference to the Str object in this Reference object (Phantomreference is different from WeakReference, SoftReference).

Combined application of reference mechanism and complex data structure

By understanding the GC mechanism, the reference mechanism, and with the referencequeue, we can implement some complex data types that prevent memory overflow.

For example, SoftReference has the trait of building a cache system, so we can implement a simple caching system with a hash table. This ensures that you can cache as much information as possible and that the Java Virtual machine does not throw outofmemoryerror because of memory leaks. This caching mechanism is especially suitable for long life cycles of memory objects, and it takes a long time to generate memory objects, such as cache list cover pictures. For some long life cycles, but with little overhead in generating memory objects, using WeakReference can achieve better memory management results.

Attached to the source of Softhashmap, I believe that after watching, we will have a more in-depth understanding of the application of the reference mechanism.

1package Com.***.widget;
2
3//: Softhashmap.java
4import java.util.*;
5import java.lang.ref.*;
6
7import Android.util.Log;
8
9public class Softhashmap extends Abstractmap {
Ten/** the internal HashMap that would hold the softreference. */
One private final Map hash = new HashMap ();
/** the number of "hard" references-to-hold internally. */
private final int hard_size;
/** the FIFO list of hard references, order of last access. */
Private final LinkedList Hardcache = new LinkedList ();
/** Reference queue for cleared SoftReference objects. */
+ Private Referencequeue queue = new Referencequeue ();
18
//strong Reference Number
Public Softhashmap () {this (100);}
Softhashmap public (int hardsize) {hard_size = hardsize;}
22
23
public object get (object key) {
Object result = null;
+//We get the SoftReference represented by that key
SoftReference soft_ref = (softreference) hash.get (key);
if (soft_ref! = null) {
//From the softreference we get the value, which can
+//NULL if it is not in the map, or it is removed in
//The Processqueue () method defined below
result = Soft_ref.get ();
if (result = = null) {
If the value has been garbage collected, remove the
//entry from the HASHMAP.
Hash.remove (key);
PNS} else {
//We Now add this object to the beginning of the
//reference queue. One reference can occur more than
+//Once, because lookups of the FIFO queue is slow, so
$//We don ' t want to search through it per time to remove
Duplicates//.
//keep recent use object in memory
Hardcache.addfirst (result);
if (Hardcache.size () > Hard_size) {
//Remove The last entry if list longer than hard_size
Hardcache.removelast ();
48}
49}
50}
return result;
52}
53
/** We define our own subclass of SoftReference which contains
Only the value of the also the key to make it easier to find
The entry in the HashMap after it ' s been garbage collected. */
$ private Static class Softvalue extends SoftReference {
$ private final Object key; Always make data member final
/** did you know that an outer class can access private data
The methods of an inner class? I didn ' t know that!
I thought it is only the inner class who could access the
Outer class ' s private information. An outer class can also
Inner class inside its inner by access private members of
Class. */
Softvalue Private (object K, Object key, Referencequeue q) {
The super (k, q);
This.key = key;
68}
69}
70
/** here we go through the Referencequeue and remove garbage
Collected Softvalue objects from the HashMap by looking them
Up using the Softvalue.key data member. */
Processqueue public void () {
Softvalue SV;
(SV = (softvalue) queue.poll ()) = null) {
if (sv.get () = = null) {
LOG.E ("Processqueue", "null");
}else{
LOG.E ("Processqueue", "not NULL");
81}
Hash.remove (Sv.key); We can access private data!
LOG.E ("Softhashmap", "release" + Sv.key);
84}
85}
/** Here we put the key, value pair into the HASHMAP using
A Softvalue object. */
A public object put (object key, object value) {
Processqueue (); Throw out garbage collected values first
LOG.E ("Softhashmap", "put into" + key);
Hash.put return (Key, new Softvalue (value, key, queue));
92}
The. Public object remove (object key) {
94 Processqueue (); Throw out garbage collected values first
Hash.remove return (key);
96}
$ public void Clear () {
98 hardcache.clear ();
Processqueue (); Throw out garbage collected values
Hash.clear ();
101}
102 public int size () {
103 Processqueue (); Throw out garbage collected values first
104 return Hash.size ();
105}
106 Public Set EntrySet () {
107//No, no, may not do!!! Grrr
108 throw new Unsupportedoperationexception ();
109}
110}

Poor performance, serious also caused by throwing OutOfMemoryError, causing the program to crash.

Avoidance of memory leaks under normal circumstances

Understanding and solving of Java memory leaks

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.