Routine - think from OutOfMemoryError caused

Watch the video to learn how to initiate the process of OOM and troubleshooting, and video .

Through this video to learn about a lot of knowledge and methods of debug JVM recorded as follows.

problem

There are three common OutOfMemoryError:

  • java.lang.OutOfMemoryError: Java heap space heap space
  • java.lang.OutOfMemoryError: Java metaspace dimensional space
  • java.lang.OutOfMemoryError: Java perm gen permanent generations

step

Achieve OOM

Create a OOM.java file, as follows, since the full implementation of java files on the command line window, although the project file in the package, but the package name will be added in the command line compiler error, so do not add:

import java.util.HashMap;
import java.util.Map;

public class OOM {
    public static void main(String[] args) {
        Map cache = new HashMap();
        for (int i = 0; i < 128; i++) {
            cache.put(i, new byte[1024 * 1024]);
        }
    }
}

This time using the javac command to compile: javac OOM.javawill appear warning, because the Map does not use generics, can be ignored.

Use the java command to run OOM.class file, then you need to set the size of memory to run, because a bunch of objects command creates a size of 128 m:

F:\Code\Java\java-demo\src\oom>java -Xmx128m OOM
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at OOM.main(OOM.java:8)

So far, causing OutOfMemoryError success.

Get a snapshot Heap Dump

Two methods:

the first

Add parameters when you start java virtual machine using the command -XX:+HeapDumpOnOutOfMemoryError:

F:\Code\Java\java-demo\src\oom>java -Xmx128m -XX:+HeapDumpOutOfMemoryError OOM
Unrecognized VM option 'HeapDumpOutOfMemoryError'
Did you mean '(+/-)HeapDumpOnOutOfMemoryError'?
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

F:\Code\Java\java-demo\src\oom>java -Xmx128m -XX:+HeapDumpOnOutOfMemoryError OOM
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid12992.hprof ...
Heap dump file created [122989308 bytes in 0.114 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at OOM.main(OOM.java:8)

Here I will be the first entry errors also wrote in, just to show Errors also occur during the experiment, but I think jdk will be prompted to add the (+/-)HeapDumpOnOutOfMemoryErrorparameters, this time by being given the information to know the original parameter wrong , and a second input on the correct implementation heap Dump I want to get a snapshot, which can help me analyze the information heap memory.

In this case more than a file directory java_pid12992.hprof, in the third step will be to learn how to analyze the snapshot file. However, before the analysis, and then try the second method to get a snapshot.

second

The first method is to add parameters before running a good snapshot, but if you are in a program that is already running, how to add parameters can get a snapshot of it?

First, the above-described modified file to slow down the speed of generating the OOM:

import java.util.HashMap;
import java.util.Map;

public class OOM {
    public static void main(String[] args) throws Exception {
        Map cache = new HashMap();
        for (int i = 0; i < 128; i++) {
            Thread.sleep(1000);
            cache.put(i, new byte[1024 * 1024]);
        }
    }
}

Use jpsthe command java can see the currently running process:

F:\Code\Java\java-demo\src\oom>jps
17160 GradleDaemon
8984 Jps

Next will use the jmapcommand to add a snapshot of the process, look at how you can use this command:

F:\Code\Java\java-demo\src\oom>jmap -help
Usage:
    jmap [option] <pid>
        (to connect to running process)
    jmap [option] <executable <core>
        (to connect to a core file)
    jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server)

where <option> is one of:
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system

Input jmap -helpcan see a lot of parameters, I pick out the part which requires the use of:

F:\Code\Java\java-demo\src\oom>jmap -help

    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>

jmap -dump:live,format=b,file=heap.bin <pid> Remember this command, so when you need to add this while running.

Like the first method, like compile and run:

// compile
F:\Code\Java\java-demo\src\oom>javac OOM.java 
// run
F:\Code\Java\java-demo\src\oom>java -Xmx128m OOM

······ // will wait about two minutes, and then print OutOfMemoryError

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at OOM.main(OOM.java:9)

This time need to open another command line window, use the jpsView process running number, this number is behind the pid parameters:

F:\Code\Java\java-demo\src\oom>jps
16272 OOM
8592 Jps
17160 GradleDaemon

Input parameters:

F:\Code\Java\java-demo\src\oom>jmap -dump:live,format=b,file=16272.hprof 16272
Dumping heap to F:\Code\Java\java-demo\src\oom\16272.hprof ...
Heap dump file created

At this time, referring to the directory can be seen, there are two snapshots, respectively, is done using two methods:

2019/11/30  14:10       105,162,801 16272.hprof
2019/11/30  13:50       122,989,308 java_pid12992.hprof
2019/11/30  14:08               651 OOM.class
2019/11/30  14:07               307 OOM.java

Explanation

These methods are the parameters HotSpot virtual machine, that is, may not apply the same procedures and parameters to get the Heap Dump snapshot on other virtual machines.

JVM threw OOM, but the JVM is still running, but more slowly due to insufficient memory response, this time if some operations are not memory-intensive presence can still perform.

Analysis OOM

OOM is how did it?

Need to know the principles of GC, GC judgment of garbage is memory object reachability analysis, GC Roots objects are considered the starting point, starting from the GC Root, has been searching down. GC Root reachable objects do not need to recover other objects to clean up.

At this point there may be cases has not been cleaned up some objects appeared, heap full, generated OOM.

It is also possible that the new object is too large, but without a large heap space can accommodate (since the previous cleaning space such as a heap fragmentation), generated at this time OOM.

Generating the OOM summarized reasons: code issue 50% (according to the present embodiment OOM.java), 40% Allocation (-Xmx128m the present embodiment), is really not enough memory is 10%.

Analysis Snapshot common tools

VisualVM

VisualVM, JDK 9+ need to download their own version, this machine uses JDK 8, the command line jvisualvmyou can call.

Look at the JDK comes with VisualVM, enter the JDK bin directory, look at the frequently used programs:C:\Program Files\Java\jdk1.8.0_221\bin

program effect
jar.exe Bale
java.exe Start the virtual machine, run the bytecode files
javac.exe Compile java files
javadoc.exe Api file generation
javap.exe Decompile, view bytecode
jcmd.exe Virtual machine running commanding
jdb.exe debugging
jmap.exe Create a snapshot Dump
jps.exe All current java process running on the computer
jstack.exe
jstat.exe Check the status of the entire jvm
jvisualvm.exe Call VisualVM

Simply run the program to see what happens, enter the command jvisualvm, the command line window to run java -Xmx128m OOM, then you can see the emergence of local OOM this process, you can double-click the connection, and then see the virtual machine input parameters at startup.

Can be seen opening the monitor heap Metaspace is progressively larger.

Just select the snapshot Heap Dump loaded, you can check the inside of the case:

Occupy memory can be seen the most is byte[],

MAT

Open source Eclipse Memory Analyzer, can be downloaded from the official website. Import snapshot earlier.

The following two main areas where analysis is a snapshot:

Histogram

The main view and selected Class object that raised the OOM. Examples of statistical objects of each class, there can be seen two portions Shallow Heap and Retained Heap.

would like to explain the concept retained by the following description: A hypothesis objects need to be recovered, this recovery time can be simultaneously A, C, E three objects, this time corresponding Retained Heap relatively large.

If this is the case below, the recovery of only the object A, the object B as an object points to C, this time corresponds Retained Heap becomes small.

Dominator Tree

占据内存空间很大的对象以及使他们一直存在的原因是什么,截了个图,可以看到是 main 线程保留着这些对象

Leak Suspects

也是主要使用的功能,可以分析可能发生溢出的原因。

Top Components

给出占据堆内存超过 1% 的组件。

Heap Dump 分析

一般来说有两个原因导致 heap 溢出:

Metaspace / PermGen —— Class 对象没有被正确的释放,尤其是 ClassLoader,一般来说自己不写 ClassLoader 里面最多只有几十个,如果发现 ClassLoader 数量过多则应该在 Metaspace / PermGen 寻找问题

Heap space —— 瞄准占空间最大的对象

通过这些工具的查看,找到溢出的 Class 对象,使用 Merge Shortest Paths to GC Roots 功能就可以找到一些 Path to GC Roots 路径,这些路径显示了这些对象是如何相互引用以及避免了垃圾回收,最终引发 OOM 的 Error 信息。找到这些信息后,通过修改代码规避这些问题,修复这些 bug。

Guess you like

Origin www.cnblogs.com/chenxianbin/p/11963535.html