1, Java memory leak introduction
First clear the concept of memory leaks: memory leak refers to the program running process dynamically allocated memory, but at the end of the program this memory is not released, resulting in this block of memory is not available, this is the memory leak, restart the computer can solve the problem, but there is a possibility of a memory leak again, Memory leaks are not related to hardware, which is caused by flaws in software design.
The reason for the memory leak in Java is very clear, that is, long declaration cycle objects hold a reference to a short declaration period object is likely to occur memory leaks. Although a short lifecycle object is no longer needed, it is a scenario where a Java memory leak occurs because the long lifecycle object is holding its reference and cannot be recycled by GC.
Examples of Java memory leak scenarios:
When we continue to add elements to the collection class, and there is no corresponding deletion mechanism, resulting in memory has been occupied, so it will not necessarily cause memory leaks, when the collection class is only a local variable, when the method is completed to exit, the natural GC will be recycled, But the fear is that the collection class is a global property (such as a static variable in a class) that causes the collection class to consume only as much memory as it does, causing the memory to leak. So when we use the Global collection class, we should pay attention to providing the appropriate deletion policy or the periodic cleanup strategy.
Memory leaks can be grouped into 4 categories:
(1) Frequent memory leaks: A memory leak of the code will be executed multiple times, each time there will be a memory leak.
(2) Accidental memory leakage: the memory leak of the code only in certain circumstances will occur, frequent and incidental is relative, for a specific environment, incidental is often hair. Therefore, test methods and test environments are important for detecting memory leaks.
(3) One-time memory leak: The memory leak of the code will only be executed once, also in memory there is always a piece of memory is not available.
(4) Implicit memory leakage: The program in the process of continuous allocation of memory, until the end of the program will release all memory, strictly speaking, there is no memory leak, because the program eventually released all the memory requested. But for a server program, it often executes for many days or even months, so that memory overflows happen sooner or later. So, we call this kind of memory leak as an implicit memory leak.
2, Java Memory overflow problems and solutions
The memory managed by the JVM is roughly divided into three different types of memory areas:
Generation Space (permanent Save area), Heap space (heap area), Javastacks (Java stack). Where the permanent storage area mainly store class (class) and meta information, class is first load of the time is put into the Permgenspace area, class needs to store content mainly includes methods and static properties. The heap area is used to hold an instance of the class (that is, an object), and the content that the object needs to store is mostly non-static. Each time an object instance is created with new, the object instance is stored in the heap area, which is also managed by the JVM's garbage collection mechanism. The Java stack is similar to most programming languages, including the stack functions of assembly language, the main basic type variables and the input and output parameters of the method. Each thread in the Java program has a separate stack. Memory-overflow problems that can easily occur include: permanent Generation space and heap spaces.
The first kind of outofmemoryerror:permgenspace
This problem occurs because of the use of a large number of jar or class in the program, so that the Java Virtual machine load class space is not enough, and permanentgeneration spaces. There are two ways to solve such problems:
(1) Increase the size of the xx:permsize and xx:maxpermsize parameters in the Java Virtual machine, where xx:permsize is the initial permanent save area size, Xx:maxpermsize is the maximum permanent save area size. For tomcat6.0, add one line to the end of a series of environment variable name descriptions in the catalina.sh or Catalina.bat file (around 70 lines): java_opts= "-XX:PERMSIZE=64M-XX: Maxpermsize=128m "If it is a Windows server, it can also be set in the system environment variable. This memory overflow error can easily occur when you feel a program that publishes Sprint+struts+hibernate schemas with Tomcat. Using the above methods, I successfully resolved the problem of frequent downtime for Tomcat servers deploying SSH projects.
(2) Clean up the jar under the Web-inf/lib in the application, if Tomcat deploys multiple applications, many applications use the same jar, can move the common jar under Tomcat common LIB, reduce the duplicate load of the class. This method is recommended by some people on the Internet, I have not tried, but the feeling can not reduce too much space, the most reliable or the first method.
The second kind of outofmemoryerror:javaheap space
This problem occurs because the Java virtual machine creates too many objects, and in between garbage collection, the virtual machine allocates the heap memory space that is already full, related to Heapspace. There are two ways to solve such problems:
(1) Check the program to see if there is a dead loop or unnecessary duplication to create a large number of objects. After you find the reason, modify the program and algorithm.
I used to write a text clustering algorithm for tens of thousands of text records (about 10 of the eigenvectors of each record), because of the problem in the program details, led to the Javaheap
Space memory overflow problem, later through the modified program was resolved
(2) Increase the size of the XMS (initial heap size) and XMX (maximum heap size) parameters in the Java Virtual machine. For example: setjava_opts=-xms256m-xmx1024m 3, Java GC mechanism
A good programmer must understand the principle of GC, how to change the performance of GC, and how to interact with GC with limited interaction, because some programs have higher performance requirements, such as embedded systems, real-time systems, etc.
Fully improve the efficiency of memory management, in order to effectively improve the performance of the program.
The basic principle of GC:
Java memory Management is actually the management of objects, including the allocation and release of objects
For programmers, the allocation object uses the new keyword, releasing the object is to assign all references to the object null, so that the program can not access the object, we call the ' unreachable ' state, the GC is responsible for retrieving all the unreachable state of the memory space.
For GC, when a programmer creates an object, the GC begins to monitor the size, address, and usage of the object. Generally, GC uses a direction graph to manage all objects in the heap (heap). This is the way to determine which objects are accessible and which objects are unreachable, and when the GC determines that some objects are unreachable, the GC has the responsibility to recycle those objects. However, in order to ensure that GC can be implemented on different platforms, the Java specification does not strictly regulate many behaviors of GC. For example, there are no clear rules on what type of recovery algorithm to use and when to recycle. Therefore, the implementations of different JVMs often have different implementation algorithms.
This also brings a lot of uncertainty to the development of Java programmers. In this paper, several problems related to GC work are studied to reduce the negative impact of this uncertainty on Java programs.
Incremental GC (incremental GC)
The GC is typically implemented by one or a group of processes in the JVM itself, which occupies heap space as well as the user program and consumes the CPU at run time. When the GC process is running, the application stops running. Therefore, when the GC is running for a long time, the user can feel the pause of the Java program, on the other hand, if the GC is running too short, the object recovery rate may be too low, which means that there are many objects that should be recycled are not recycled, still occupy a lot of memory. Therefore, when designing a GC, you must weigh the pause time against the recovery rate. A good GC implementation allows users to define the settings they need, such as some limited memory devices, very sensitive to memory usage, and expect the GC to be able to reclaim memory accurately, and it does not care about slowing down the speed of the program. In addition to some real-time online games, it is not possible to allow a program to be interrupted for a long time. Incremental GC is the use of a certain recovery algorithm, a long break, divided into many small interrupts, in this way to reduce the effect of GC on user programs. Although an incremental GC may not be as efficient as a regular GC in overall performance, it can reduce the maximum downtime of a program. The HotSpot JVM provided by the Sun JDK supports the incremental gc.hotspot JVM default GC method for not using incremental GC, in order to start an incremental GC, we must increase the-XINCGC parameters when running the Java program.
HotSpot JVM Incremental GC is implemented using the train GC algorithm. The basic idea is to group all the objects in the heap by grouping (tiering) in terms of creation and usage, putting objects in the first team with frequently high and relevant dependencies, and constantly adjusting the group as the program runs. When the GC is running, it always reclaims the oldest (most recently infrequently accessed) objects, and if the entire group is recyclable, the GC reclaims the entire group. In this way, each GC run only a certain proportion of the unreachable object, to ensure the smooth operation of the program.
Detailed Finalize function
Finalize is a method that is located in the object class, which has an access modifier of protected, because all classes are subclasses of object, so it is easy for a user class to access this method. Since the Finalize function does not automatically implement chained calls, we must implement them manually, so the last statement of the Finalize function is usually super.finalize ().
In this way, we can implement a finalize call from bottom to top, that is, releasing its own resources before releasing the resources of the parent class. According to the Java language Specification, the JVM guarantees that this object is not reachable until the Finalize function is invoked, but the JVM does not guarantee that the function will be invoked. In addition, the specification guarantees that the Finalize function runs at most once. Many Java beginners will think that this approach is similar to the destructor in C + +, where the release of many objects and resources is placed in this function. In fact, this is not a very good way. There are three reasons:
First, in order to be able to support the Finalize function, the GC has a lot of additional work to do with the object that overrides the function.
Second, after the finalize run is complete, the object may become reachable, and the GC will check again if the object is reachable. Therefore, using finalize will reduce the performance of the GC.
Third, since the GC call finalize time is indeterminate, releasing resources in this way is also uncertain. Typically, finalize is used for the release of some easily controlled and very important resources, such as some I/O operations, data connections. The release of these resources is critical to the entire application. In this case, the programmer should focus on the resources that are managed by the program itself, including releasing them, as a supplement to the Finalize function, releasing the resources, creating an insurance management mechanism rather than relying solely on finalize to release resources.