Java Memory leakage

Source: Internet
Author: User
It is easy to handle Java Memory leakage-Linux general technology-Linux programming and kernel information. The following is a detailed description. Abstraction

Although java virtual machines and garbage collection mechanisms manage most of the memory transactions, there may still be memory leaks in java software. Indeed, memory leakage is a common problem in large projects. The first step to avoid Memory leakage is to understand the cause of their occurrence. This article introduces some common defects and provides some very good practice examples to guide you to write code without memory leakage. Once your program has memory leakage, it is very difficult to find out the cause of the leakage in the code. At the same time, this article also introduces a new tool to find memory leaks and then specify the root cause. This tool is easy to use and allows you to find memory leaks in product-level systems.

Garbage Collection (GC) Role

Although garbage collection is concerned with most of the problems, including memory management, which makes the programmer's tasks easier, the programmer may still make some mistakes and cause memory leakage. GC (garbage collection) recursively references all inherited objects from the "root" (Objects in the stack, static data members, JNI handles, etc, mark all the living objects that can be accessed. These objects become the only objects that can be manipulated by the program, and other objects are released. This is safe because GC makes the program unable to access the released objects.

Memory management can be said to be automatic, but this does not leave programmers out of memory management issues. For example, there is always a certain amount of overhead for memory allocation (and release), although these overhead are implied by programmers. If a program creates many objects, the execution speed of the program is slower than that of the program that completes the same task and creates fewer objects (the content provided by other programs is the same ).

The main cause of Memory leakage is that I forgot to release the memory I previously applied. If a reference to useless objects exists in the program, these objects will reside in the memory and consume the memory, because the Garbage Collector cannot verify whether these objects are no longer needed. As we can see earlier, if an object is referenced, this object is defined as "alive" and will not be released. To determine that the memory occupied by an object will be recycled, the programmer must confirm that the object will no longer be used. A typical practice is to set the object data member to null or remove the object from the set. Note: When local variables are not needed, you do not need to explicitly set them to null because these references are automatically cleared when a method is executed.

At a higher level, this is what memory leakage is considered by all languages with memory management. The remaining object references will no longer be used.

Typical Leakage

Now that we know that there is indeed a memory leak in java, let's look at some typical leaks and find out why they happen.

Global set

It is common to have a variety of global data warehouses in large applications, such as a JNDI-tree or a session table. In these cases, the focus is on managing the data warehouse size. Of course, there are some appropriate mechanisms to remove useless data from the repository.

There are many different solutions. The most common solution is to clear jobs that run cyclically. This job will verify the data in the repository and then clear all unnecessary data.
Another method is to use reference calculation. The set is used to understand the number of referrer for each set. This requires when the notification set of the associator will be completed. When the number of associators is zero, you can remove related elements from the set.

High-speed cache

Cache is a data structure used to quickly find the results of operations that have been executed. Therefore, if an operation is slow, you can first put the common input data into the cache, and then call the data in the cache later.

There is also a dynamic implementation of high-speed cache. When the data operation is completed, it is sent to the high-speed cache. A typical algorithm is as follows:

1. Check whether the result is in the cache. If yes, the result is returned;

2. if the result is not there, calculate the result;

3. Add the results to the cache for future operation calls.

This algorithm problem (or potential memory leakage) is at the end. If an operation is accompanied by a different number, it is also a very large result to be saved to the cache. This method is not competent.

To avoid this potentially fatal design error, the program must determine that the cache has an upper bound in the memory used by the program. Therefore, a better algorithm is:

1. Check whether the result is in the cache. If yes, the result is returned;

2. if the result is not there, calculate the result;

3. If the cache occupies too much space, remove the old results from the cache;

4. Add the results to the cache for future operation calls.

By constantly Removing old results from the cache, we can assume that in the future, the probability of the latest input data being reused will be much greater than the old results. This is usually a good idea.

This new algorithm ensures that the cache capacity is in a predetermined range. It is difficult to calculate the exact range because the objects in the cache will continue to be valid when referenced. Correct division of the cache size is a complex task. You must weigh the contradiction between the available memory size and fast data access.

Another way to solve this problem is to use the java. lang. ref. SoftReference class to insist on putting objects into high-speed cache. This method ensures that the reference of these objects can be released when the VM runs out of memory or requires more heaps.

Class Loader

The creation of Java class loaders has many vulnerabilities that may cause memory leakage. Due to the complex structure of the Class Loader, it is difficult to obtain the perspective of Memory leakage. These difficulties are not only because the class loader is only related to the "common" object reference, but also to the internal reference of the object, such as data variables, methods, and various types. This means that as long as there is a Class Loader for data variables, methods, various types and objects, the class loader will reside in JVM. Since the class loader can be associated with many classes and static data variables, a considerable amount of memory may leak.

Locate Memory leakage

Often, the initial sign of program memory leakage occurs after an error, and an OutOfMemoryError is returned in your program. This typical situation occurs in the product environment, where you want to minimize the possibility of Memory leakage and debugging. Maybe your testing environment is different from the system environment of the product, and the leaked ones will only be revealed in the product. In this case, you need a low housekeeping tool to monitor and find memory leaks. At the same time, you also need to associate this tool with your system, instead of restarting it or automating your code. Perhaps more importantly, when you do the analysis, you need to be able to separate the tool so that the system will not be disturbed.

An OutOfMemoryError is often a sign of Memory leakage. It is possible that the application uses too much memory. At this time, you cannot increase the number of JVM heaps, you cannot change your program to reduce memory usage. However, in most cases, an OutOfMemoryError is a sign of Memory leakage. One solution is to continue listening for GC activities and check whether the memory usage increases over time. If yes, there must be a memory leakage in the program.

Detailed output

There are many ways to monitor the activity of the garbage collector. Perhaps the most widely used is to run jvm with the:-Xverbose: gc option, and then observe the output results for a period of time.

[Memory] 10.109-10.235: GC 65536 K-> 16788 K (65536 K), 126.000 MS

The value after the arrow (16788 K in this example) is the heap Usage After garbage collection.

Console

Observing these endless GC detailed statistical outputs is a very tedious task. Fortunately, there are some tools to do these tasks in place of us. The JRockit Management Console outputs The heap usage graphically. By observing images, we can easily observe whether the heap usage increases with time.




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093816464.gif'); ">

Figure 1. The JRockit Management Console


The management console can even be configured to send emails to you when the heap usage is faulty (or other events occur. This clearly makes it easier to monitor memory leakage.
Memory leak detection tool

There are many dedicated memory leak detection tools. Among them, The JRockit Memory Leak Detector can be used to observe The Memory leakage and find out The cause of The leakage. This powerful tool is tightly integrated into JRockit JVM and provides the lowest possible memory transactions and easy access to the Virtual Machine heap.

Advantages of specialized tools

Once you know that there is a memory leak in the program, you need more professional tools to find out why there is a leak. JVM cannot tell you. Many tools are available now. In essence, these tools obtain information about the JVM storage system through two methods: JVMTI and bytecode instruments. Java Virtual Machine Tool interface (JVMTI) and its original form of JVMPI (pressure Interface) are both standard interfaces, as an external tool to communicate with JVM and collect JVM information. Bytecode is a pre-processing technique that references the byte information required to obtain the tool through a probe.

Using these technologies to detect memory leaks has two drawbacks, which makes their use in product-level environments less ideal. First, it is not negligible to downgrade the memory usage and memory transaction performance based on the two. The heap usage information obtained from JVM must be exported, collected, and processed in the tool. This means to allocate memory. Exporting Information Based on JVM performance requires overhead. The Garbage Collector runs very slowly when collecting information. Another drawback is that the information required by these tools is related to JVM. It is obviously impossible to associate the tool with the JVM when it starts to run, while separating the tool while keeping the JVM running during analysis.

Since JRockit Memory Leak Detector is integrated into JVM, the above two disadvantages are no longer applicable. First, most of the processing and analysis are done in JVM, so no data needs to be transferred or rebuilt. Processing can also be carried on the back of the garbage collector, which means improving the speed. In addition, the memory leak detector can be associated and separated with the same running JVM, as long as the JVM starts with the-Xmanagement option (this allows listening and managing JVM through the remote JMX interface ). After the tool is separated, the tool does not leave anything in the JVM; the JVM can run the code at full speed, just like before the tool is associated.

Trend Analysis

Let's take a deeper look at this tool and learn how it captures memory leaks. When you understand that there is a memory leak in the Code, the first step is to calculate what data is leaking-which object class causes leakage. The JRockit Memory Leak Detector calculates The existing objects contained in each class during garbage collection. If the number of object members of a class increases over time (growth rate), there may be leakage.




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093817717.gif'); ">

Igure 2. The trend analysis view of the Memory Leak Detector

Because a leak is likely to be as small as water drops, trend analysis must run for a long enough period of time. During each short period of time, the increase of local classes will delay the leakage. However, memory transactions are very small (the largest memory transaction is composed of a packet sent from JRockit to the memory leak detector during each garbage collection ). Memory transactions should not be a problem with any system-or even a program that runs at full speed in the product stage.

At the beginning, numbers will jump a lot. As time goes on, these numbers will become stable and then show which classes will keep increasing.

Find Root Cause

Classes of those objects will cause leakage, and sometimes it is enough to prevent the leakage. This class may only be used in a very limited part, and the problem can be found through quick inspection. Unfortunately, this information is insufficient. For example, the object class java. lang. String that often causes memory leakage, but the String class is applied to the entire program, which becomes helpless.

What we want to know is whether other objects will cause memory leakage. For example, in the String class mentioned above, why do these leaked objects still exist around? Which references point to these objects? The object in this column contains references to the String class, which becomes too large and meaningless. To limit the number of data, we can organize them into a group through classes, so that we can see that the objects of other classes will still leak objects (String class ). For example, put a String class into Hashtable, where we can see the Hashtable entry associated with the String class. From the Hashtable entry, we finally find the Hashtable objects associated with the String class (see below ).




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093817106.gif'); ">

Figure 3. Sample view of the type graph as seen in the tool
Work backward

Since the beginning, we have been focusing on object classes rather than individual objects. We do not know that the Hashtable has been leaked. If we can find out how big the Hashtable is in the system, we can assume that the largest Hashtable has a leak (because it can aggregate enough leaks to become very large ). Therefore, all Hashtable and all the data involved can help us find out the precise Hashtable that causes leakage.




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093818431.gif'); ">

Figure 4. Screenshot of the list of Hashtable objects and the size of the data they are holding live

The data overhead involved in computing an object is very large (this requires referencing a chart along with that object to run as the root) and it takes a lot of time to process this for each object. Knowing some implementation mechanisms inside Hashtable can lead to shortcuts. Internally, A Hashtable has an array entry of Hashtable. The growth of arrays is accompanied by the growth of objects in Hashtable. Therefore, to find the largest Hashtable, We can restrict the search to the largest array containing the Hashtable reference entry. This makes it faster.




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093818142.gif'); ">

Figure 5. Screenshot of the listing of the largest Hashtable entry arrays, as well as their sizes.

Drill Down

When we find the leaked Hashtable instance, we can find other Hashtable instances and use the above method to find the Hashtable instance.




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093818889.gif'); ">

Figure 6. This is what an instance graph can look like in the tool.

For example, a Hashtable can have an object reference from MyServer, while MyServer contains an activeSessions data member. This information is enough to go deep into the code to find out the problem.




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093818313.gif'); ">

Figure 7. Inspecting an object and its references to other objects

Find the allocation point

It is very useful to find out where the leaked objects are when Memory leakage is detected. There may not be enough information to know the relationship between them and other related objects, but it is helpful to know the information they have been created there. Of course, you will not be willing to create a tool to print all the allocated stack paths. You are not willing to run a program in a simulated environment just to capture a memory leak.

With JRockit Memory Leak Detector, program code can dynamically allocate the stack Creation Path in the Memory. These stack paths can be accumulated and analyzed in tools. If you do not enable this tool, this feature will not be consumed, which means you are always ready to start. When a path needs to be allocated, the JRockit compiler can monitor the memory allocation instead of the code, but only apply to the desired class. Even better, after data analysis, the generated mechanical code will be completely removed without causing any execution efficiency decline.




(400) {this. resized = true; this. width = 400; this. alt = 'click here to open new window';} "onmouseover =" if (this. resized) this. style. cursor = 'hand'; "onclick =" window. open ('HTTP: // java.chinaitlab.com/UploadFiles_8734/200604/20060427093818501.gif'); ">

Figure 8. The allocation stack traces for String during execution of a sample program

Summary

It is very difficult to find out memory leaks. Some good practices in this article to avoid leaks include keeping in mind what is put into the data structure at all times, so as to monitor unexpected growth in memory more closely.

We also saw how JRockit Memory Leak Detector captures Memory leaks in product-level systems. This tool detects leakage in three steps. 1. Identify leakage of object classes through trend analysis; 2. Identify other classes related to the same leakage object; 3. Explore down and observe how independent Objects interact with each other. At the same time, the tool can also dynamically find the stack path for all memory allocations. Using these three features, the tool is tightly integrated into the JVM, so that it can be safe and effective to capture and fix memory leaks.
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.