Understanding memory leaks in Java and how to resolve them _java

Source: Internet
Author: User
Tags garbage collection int size object object static class

This article describes in detail the principles of Java memory management, as well as the causes of memory leaks, while providing a number of columns to solve the Java memory leaks, and I hope to help you Java developers.

Java Memory Management mechanism

In the C + + language, if a piece of memory needs to be allocated dynamically, the programmer needs to be responsible for the entire lifecycle of that memory. From the application allocation, to the use, then to the final release. Such a process is very flexible, but very cumbersome, programmers can easily inadvertently forget to release memory, resulting in memory leaks. The Java language optimizes memory management, which is the garbage collection mechanism. Almost all of Java's memory objects are allocated on heap memory (except for basic data types), and the GC (garbage collection) is responsible for automatically reclaiming memory that is no longer in use.

The above is the basics of the Java Memory management mechanism. But if we only understand this, we will still experience a memory leak in actual project development. Perhaps some people doubt that, since the Java garbage collection mechanism can automatically reclaim memory, how can there be memory leaks? In this question, we need to know when the GC reclaims the memory object and what memory object is considered "no longer in use" by GC.

Java in the access to memory objects, using the way of reference. In Java code we maintain a reference variable of a memory object, through which we can access the memory object space in the corresponding memory address through the value of the reference variable. In a Java program, the reference variable itself can be stored in both heap memory and in the memory of the code stack (the same as the basic data type). The GC thread starts tracing from the reference variable in the code stack to determine which memory is being used. If the GC thread fails to trace a heap of memory in this way, then the GC considers that the memory will no longer be used (because the memory is already inaccessible in the code).

With this graph of memory management, when a memory object loses all references, the GC can recycle it. Conversely, if the object still has a reference, it will not be reclaimed by GC, even if the Java virtual machine throws OutOfMemoryError.

Java memory leaks

There are generally two cases of memory leaks. A situation such as in the C + + language, the allocated memory in the heap, when it is not released, erase all Access to this memory (such as pointer redistribution), and the other is to retain the memory and the way it is accessed (referenced) when the memory object is clearly not needed. In the first case, it has been well solved in Java due to the introduction of garbage collection mechanism. 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:

Copy Code code as follows:

Vector v = new vector (10);
for (int i = 1; i < i + +) {
Object o = new Object ();
V.add (o);
o = null;
}

In this example, there is a reference o to the vector object's Reference V and object in the code stack. In the For loop, we constantly generate new objects, add them to the Vector object, and then place an O reference empty. The problem is that when the O reference is empty, if GC occurs, can we create an object that is collected by GC? The answer is in the negative. Because the GC finds a V reference when it tracks a reference in the code stack, and continues to trace it, it finds a reference to the object in the memory space that the V reference points to. That is, although the O reference is already empty, the object object still has other references that can be accessed, so the GC cannot release it. If the object object has no effect on the program after this loop, then we think that the Java program has a memory leak.

Although the Java memory leak is less disruptive to memory leaks in C + +, the program still works in most cases, except in a few cases where a program crash occurs. However, in the case of mobile devices with tighter memory and CPU restrictions, Java memory overflows can cause problems such as inefficient programs and large amounts of unwanted memory. This will result in poor performance of the entire machine, which can cause the outofmemoryerror to be thrown, causing the program to crash.

Avoid memory leaks in general

In general, where complex data structures are not involved, the Java memory leak behaves as if the lifecycle of one memory object exceeds the length of time that the program needs it. We sometimes refer to it as "object dissociation".

For example:

Copy Code code as follows:

public class filesearch{
Private byte [] content;
Private File Mfile;
Public filesearch (file file) {
Mfile = file;
}
public boolean hasstring (String str) {
int size = GetFileSize (mfile);
content = new byte [size];
LoadFile (mfile, content);
string s = new string (content);
return S.contains (str);
}
}

In this code, there is a function hasstring in the FileSearch class to determine whether the document contains the specified string. The process first loads the mfile into memory and then makes a judgment. The problem here, however, is to declare content for instance variables, not local variables. As a result, the data for the entire file still exists in memory after this function returns. It is clear that the data we are not required to follow, which caused the memory of the unnecessary waste.

To avoid a memory leak in this situation, we are required to manage our allocated memory in the memory management mindset of C + +. First, the effective scope of the memory object is clarified before the object reference is declared. A valid memory object within a function should be declared as a local variable and declared as an instance variable with the same life cycle as the class instance ... Analogy Second, when the memory object is no longer needed, remember to manually place its reference empty.

Memory leak problem in complex data structure

In the actual project, we often use some more complex data structure to cache the information that the program needs in the process of running. Sometimes, because the data structure is too complex, or we have some special requirements (for example, when memory allows, as much caching information as possible to improve the speed of the program, etc.), it is difficult to clearly define the life cycle of data in the structure. At this point, we can use a special mechanism in Java to prevent memory leaks.

As we have mentioned before, the GC mechanism of Java is based on the reference mechanism of tracking memory. Before that, the references we used were just defining an "Object o;" "In such a form." In fact, this is just one of the defaults in the Java referral 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 results we need.

Several ways of referencing in Java

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

Strong references

The references used in the content we described earlier are strong references, which is the most common reference. If an object has a strong reference, it is similar to the essential necessities of life, and the garbage collector will never reclaim it. When the memory space is low, the Java virtual machine would rather throw a outofmemoryerror error, cause the program to terminate abnormally, and not recycle the strongly referenced object to solve the out-of-memory problem.

Soft Reference (SoftReference)

A typical use of the SoftReference class is for memory-sensitive caching. The principle of softreference is to ensure that all soft references are cleared before the JVM reports out-of-memory conditions while maintaining references to objects. The key is that the garbage collector may (or may not) release soft objects at run time. Whether an object is disposed depends on the garbage collector's algorithm and the amount of memory available to the garbage collector at run time.

Weak reference (WeakReference)

A typical use of the WeakReference class is the canonical mapping (canonicalized mapping). In addition, weak references are also useful for objects whose lifetimes are relatively long and are not expensive to re-create. The point is that when the garbage collector runs, it will release the object referenced by WeakReference if it encounters a weakly accessible object. Note, however, that the garbage collector may run multiple times to find and release weakly accessible objects.

Virtual Reference (Phantomreference)

The Phantomreference class can only be used to track upcoming collections of referenced objects. Similarly, it can be used to perform pre-mortem cleanup operations. Phantomreference must be used in conjunction with the Referencequeue class. Referencequeue is needed 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 the referencequeue is a notification that the object referenced by the Phantomreference object has ended and is available for collection. This allows you to take action just before the memory consumed by the object is reclaimed. Reference and Referencequeue are used in conjunction.

The interaction of GC, Reference and Referencequeue

A, GC cannot delete memory for objects that are strongly referenced.
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, GC found a weak reference to the object memory, 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, GC found a virtual reference to the object memory, then:
The heap object referenced by ①phantomreference is declared as finalizable.
②phantomreference is added to its referencequeue before the heap object is released.
The following points are worth noting:
1, GC in general will not find soft reference memory objects, only when the memory is obviously insufficient to find and release the soft reference object memory.
2. GC discovery and release of weak references is not immediate, and sometimes a GC must be repeated to discover and release weakly referenced memory objects.
3, soft references and weak references when added to the Referencequeue, the reference to the real memory has been set empty and the associated memory has been released. When a virtual reference is added to the referencequeue, memory is not released and can still be accessed.
code example
Through the above introduction, I believe that you have a reference to Java and the similarities and differences between several ways of reference has been a certain understanding. The concept alone may be too abstract, and here's an example to show how to use the Reference mechanism in your code.

Copy Code code as follows:

String str = new string ("Hello"); ①
Referencequeue < string > RQ = new Referencequeue < string > (); Ii
WeakReference < string > WF = new WeakReference < string > (str, RQ); ③
str = NULL; ④ suppresses strong references to "hello" objects
String str1 = Wf.get (); ⑤ if the "Hello" object is not recycled, str1 references the "Hello" object
If the "Hello" object is not reclaimed, rq.poll () returns null
Reference;?  Extends String > ref = Rq.poll (); ⑥

In the above code, note ⑤⑥ two places. If the "Hello" object is not recycled 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 R Eference 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

With the GC mechanism, the referral mechanism, and the referencequeue, we can implement some complex data types that prevent memory overflows.

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 memory objects with long life cycles, and the time-consuming process of generating memory objects, such as caching list cover pictures, and more. For some long life cycles, but the overhead of generating memory objects is small, using weakreference can achieve better memory management.

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

Copy Code code as follows:

Package com. * * * widget;
: Softhashmap.java
Import Java.util. * ;
Import Java.lang.ref. * ;
Import Android.util.Log;

public class Softhashmap extends Abstractmap {
/** the internal HashMap that would hold the softreference. */
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 by last access. */
Private final LinkedList Hardcache = new LinkedList ();
/** Reference queue for cleared SoftReference objects. */
Private Referencequeue queue = new Referencequeue ();
Strong Reference Number
Public Softhashmap () {this (100);}
Public softhashmap (int hardsize) {hard_size = hardsize;}

public object get (object key) {
Object result = null;
We get the "softreference represented by" key
SoftReference soft_ref = (softreference) hash.get (key);
if (soft_ref!= null) {
From the softreference we have the value, which can be
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);
} else {
We Now add this object to the beginning of the hard
Reference queue. One reference can occur more than
Once, because lookups of the FIFO queue are slow, so
We don ' t want to search through it all 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 ();
}
}
}
return result;
}

/** We define our own subclass of SoftReference which contains
Not only the ' value but 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 this outer class can access private data
Members and methods of a 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
Access private members of the inner class inside its inner
Class. */
Private Softvalue (object K, Object key, Referencequeue q) {
Super (k, q);
this. Key = key;
}
}

/** 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. */
public void Processqueue () {
Softvalue SV;
while (SV = (softvalue) queue.poll ())!= null) {
if (sv.get () = null) {
LOG.E ("Processqueue", "null");
} else {
LOG.E ("Processqueue", "not NULL");
}
Hash.remove (Sv.key); We can access private data!
LOG.E ("Softhashmap", "release" + Sv.key);
}
}
/** we put the key and value pair into the HASHMAP using
A Softvalue object. */
The public object is put (object key, object value) {
Processqueue (); Throw out garbage collected values
LOG.E ("Softhashmap", "put in" + key);
Return Hash.put (Key, new Softvalue (value, key, queue));
}
public object Remove (Object key) {
Processqueue (); Throw out garbage collected values
return Hash.remove (key);
}
public void Clear () {
Hardcache.clear ();
Processqueue (); Throw out garbage collected values
Hash.clear ();
}
public int size () {
Processqueue (); Throw out garbage collected values
return Hash.size ();
}
Public Set EntrySet () {
No, no, you!!! Grrr
throw new Unsupportedoperationexception ();
}
}

Related Article

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.