heapdump - GANGNAM-JAVA/JAVA-STUDY GitHub Wiki
Memory Leak
ํ๋ก๊ทธ๋จ์ด OOM(Out Of Memory) ์ค๋ฅ๋ก ์ข ๋ฃ๋๊ฑฐ๋ ์คํ ์๋๊ฐ ์ ํ๋๋ ํ์.
์์ฃผ ๋ฐ์ํ๋ OOM 2๊ฐ์ง
1. java.lang.OutOfMemorryError: heap space
2. java.lang.OutOfMemorryError: GC Overhead limit exceed
์ถ์ฒ์ ๋ฐ๋ฅด๋ฉด, ์๋ฐ ํ๋ก์ธ์ค๊ฐ ์ฝ 98%์ ์๊ฐ์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ฅผ ์คํํ๋๋ฐ ์๋ชจํ๊ณ
์คํ ์ดํ์๋ 2% ์ด์์ ํ ๊ณต๊ฐ์ ๋ค์ฏ ๋ฒ ์ด์ ํ๋ณดํ์ง ๋ชปํ ๋ GC Overhead limit exceed ์์ธ๊ฐ ๋ฐ์ํ๋ค.
OOM์ ๋์ฒํ๋ ๋ฐฉ๋ฒ
ํ๋ก๊ทธ๋จ์ด OOM์ผ๋ก ์ธํด ์ข ๋ฃ๋ ๋ ์๋์ผ๋ก ๋น์์ ๋ฉ๋ชจ๋ฆฌ ์ ๋ณด๋ฅผ ํ์ผ(Heap Dump)๋ก ๋จ๊ฒจ์ผ ํ๋ค.
-XX:+HeapDumpOnOutOfMemoryError
์ ๋ช ๋ น์ด๋ฅผ ํ๋ก๊ทธ๋จ ์คํ ์ต์ ์ ์ถ๊ฐํ๋ฉด OOM์ด ๋ฐ์ํ ๋
JVM์ ์์ํ ๋๋ ํ ๋ฆฌ์ Heap Dump ํ์ผ(.hprof)ํ์ผ์ด ์๋์ผ๋ก ์์ฑ๋๋ค.
-XX:HeapDumpPath
์ ๋ช ๋ น์ด๋ Heap Dump ํ์ผ์ ์์ฑํ ์์น๋ฅผ ์ง์ ํ๋ ์ญํ ์ ํ๋ค.
์ด ํ์ผ์ด ์๋ค๋ฉด ํ์์ ์ฌํํ ํ ํ๋คํ ํ์ผ์ ์๋์ผ๋ก ๋ง๋ค์ด์ผ ํ๋ค.
๋จผ์ Heap Dump ํ์ผ์ ์๋์ผ๋ก ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๊ณ ๊ทธ ํ์ ์์ฑ๋ Heap Dump ํ์ผ์ ๋ถ์ํด๋ณธ๋ค.
Heap Dump ํ์ผ ๋ถ์ ๋ฐฉ๋ฒ์ผ๋ก๋ ํฌ๊ฒ 2๊ฐ์ง๊ฐ ์๋ค.
-
CLI
-
์ดํด๋ฆฝ์ค MAT(Eclipse Memory Analyzer)
Heap Dump๋?
Heap Dump : ํน์ ์์ ์ Heap ์ํ(์ ๋ณด)๋ฅผ ํ์ผ๋ก ๋ณต์ฌํด ์ ์ฅํ๋ ์์ .
Memory Leak์ ์์ธ์ ๋ถ์ํ ๋ ์์ฃผ ์ฌ์ฉ๋๋ค.
- Heap : ์ธ์คํด์ค๊ฐ ์ ์ฅ๋๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ
- Dump : ์ ๋ณด๋ฅผ ๋ค๋ฅธ ๊ณณ์ผ๋ก ๋ณต์ฌํด ๊ฐ์ ์ ์ฅํ๋ ๊ฒ
vi ๋ฑ์ ํด์ ์ด์ฉํด์ Heap Dump ํ์ผ์ ์ด๋ฉด ์๋๋ค.
์ฌ๋ ์์ฐ ํ์ผ์ ํ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ด์ฆ๋งํผ ์๋ฒ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก ๋ก์ปฌ ์ปดํจํฐ๋ก ๋ณต์ฌํ ํ ํ์ผ์ ์ด์ด์ผ ํ๋ค.
Heap Dump ํ์ผ ์์ฑ ๋ฐ ๋ถ์(CLI)
OOM์ด ๋ฐ์ํ๋ ํด๋์ค๋ฅผ ์์ฑํ๋ค.
import java.util.HashMap;
import java.util.Map;
public class HeapDumpTest {
private Map<Integer, MemoryObject> leak = new HashMap<>();
public static void main(String[] args) {
HeapDumpTest heapDumpTest = new HeapDumpTest();
heapDumpTest.run();
}
private void run() {
for(int i = 0; ; i++) {
// ํด์๋งต์ ์ ์ฅ๋ง ํ๊ณ ๋นผ๋ด์ง ์์ ๊ฒฐ๊ตญ OOM์ด ๋๋ ๊ตฌ์กฐ.
leak.put(i, new MemoryObject(i));
System.out.println("leaking object " + leak.get(i).index);
if( i == 5000 ) {
try {
// ๋ฐ๋ชจ๋ฅผ ์ํด 5000๋ฒ ์ดํ sleep.
System.out.println("Sleeping after adding " + i + "th element.");
Thread.sleep(100000000L);
} catch (final Exception e) {
e.printStackTrace();
}
}
}
}
class MemoryObject {
int index ;
MemoryObject(final int index) {
this.index = index;
}
}
}
5001๋ฒ์งธ MemoryObject๊ฐ leak์ ์ ์ฅ๋๋ฉด sleep ๋๋ค.
leaking object 4996
leaking object 4997
leaking object 4998
leaking object 4999
leaking object 5000
Sleeping after adding 5000 th element.
Heap Dump ํ์ผ์ ์์ฑํ๊ธฐ ์ํด JDK ๋ด์ jps ๋ช ๋ น์ด๋ฅผ ํตํด HeapDumpTest์ ํ๋ก์ธ์ค ๋ฒํธ(PID)๋ฅผ ์ฐพ๋๋ค.
$ jps
5408 Launcher
7744 KotlinCompileDaemon
14436 Jps
10460 HeapDumpTest
2348
๊ทธ๋ฆฌ๊ณ JDK ๋ด์ jmap ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํด์ Heap Dump ํ์ผ์ ์์ฑํ์
$ jmap -dump:live,file=./heapdump.hprof 10460
Dumping heap to C:\study\JAVA-STUDY\heapdump.bin ...
Heap dump file created
-
dump:live : ๋์์ค์ธ ์ธ์คํด์ค๋ง ์บก์ณ
-
file : Dump ํ์ผ ์ ์ฅ ๊ฒฝ๋ก
Dumpํ์ผ์ ํ์ธํ ํ, jhat ๋ช ๋ น์ด๋ฅผ ํตํด ํ์ผ์ ์คํ์ํจ๋ค.
$ jhat -J-Xmx6g -port 7000 ./heapdump.hprof
Reading from ./heapdump.hprof...
Dump file created Tue Jul 07 07:32:16 KST 2020
Snapshot read, resolving...
Resolving 30042 objects...
Chasing references, expect 6 dots......
Eliminating duplicate references......
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
-
Xmx : ์คํ์ํฌ ํ๋ก๊ทธ๋จ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ด์ฆ ์ค์
-
7000 : Dump ํ์ผ์ ์คํ์ํฌ ํฌํธ ์ด์ ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด https://localhost:7000 ์ฃผ์๋ก ์ ์ํด๋ณด์
์ด ํ๋ฉด์์ ๋ชจ๋ ํจํค์ง๋ค๊ณผ ํด๋์ค๋ค์ ๋ํ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค.
๋ฉ๋ชจ๋ฆฌ ์ ์ถ์ ์ฐพ๊ธฐ ์ํด "Show heap histogram" ๋งํฌ๋ฅผ ํด๋ฆญํ์.
์ด ํ๋ Total Size ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ๋์ด์๋ค.
๊ฐ๋จํ ํ๋ก๊ทธ๋จ ํ๋๋ฅผ ๋๋ ธ์ ๋ฟ์ธ๋ฐ ์๋ง์ ์ธ์คํด์ค๋ค์ด ์์ฑ๋์์์ ํ์ธํ ์ ์๋ค.
์์์ 7๋ฒ์งธ์ ์ฐ๋ฆฌ๊ฐ ์ฐพ๊ณ ์ ํ๋ ํด๋์ค ์ด๋ฆ์ด ๋ณด์ธ๋ค.
ํ์คํ 5001๊ฐ๊น์ง๋ง ์์ฑ๋์๋ค. MemoryObject๋ฅผ ํด๋ฆญํ์.
References to this object์ 5001๊ฐ์ MemoryObject ์ธ์คํด์ค๋ค ๋ฆฌ์คํธ๊ฐ ๋์จ๋ค. ์๋ฌด๊ฑฐ๋ ํ๊ฐ ํด๋ฆญํด๋ณด์.
์ด์ ์ด๋ ๋ ํผ๋ฐ์ค๊ฐ ์ด ์ธ์คํด์ค๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ์ฐพ๊ธฐ ์ํด Exclude Weak refs๋ฅผ ํด๋ฆญํ๋ค.
์ด ํ๋ฉด์ ํตํด ์ด ์ธ์คํด์ค๊ฐ ์ด๋์ ์ํ๋์ง ์ ์ ์๋ค.
์ด ์ธ์คํด์ค๋ HeapDumpTest ํด๋์ค์ leak ์ด๋ผ๋ ํ๋์ ์ฐ๊ฒฐ๋์ด ์๋ค.
๋ํ leak ํ๋๋ HashMap์ ์ธ์คํด์ค์์ ์ ์ ์๋ค.
๊ทธ๋ฆฌ๊ณ ์ด MemoryObject๋ HashMap ์ธ์คํด์ค์ table ํ๋์ ์ฐ๊ฒฐ๋์ด ์๋ค.
๊ฒฐ๊ตญ leak์ด๋ผ๋ HashMap ์ธ์คํด์ค๊ฐ MemoryObject ์ธ์คํด์ค๋ฅผ ๊ฐ์ง๊ณ ์๊ณ leak์ด Memory Leak์ ์์ธ์์ ์ ์ ์๋ค.
Heap Dump ํ์ผ ์์ฑ ๋ฐ ๋ถ์(์ดํด๋ฆฝ์ค MAT)
์ด ๋งํฌ์์ ์ดํด๋ฆฝ์ค MAT์ ๋ค์ด๋ฐ๋ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์๋ค.
์์ฑ๋ Heap Dump ํ์ผ์ MAT์ผ๋ก ์คํ์ํค๋ฉด ์์ ๊ฐ์ ํ๋ฉด์ด ๋ํ๋๋ค.
๋จผ์ ๋ช ๊ฐ์ง ์ฉ์ด๋ฅผ ์ ์ํ์.
- with incomming references : ํด๋น Object๋ฅผ ์ฐธ์กฐํ๋ Object ๋ณด์ฌ์ค
- with outcomming references : ํด๋น Object๊ฐ ์ฐธ์กฐํ๋ Object ๋ณด์ฌ์ค
- Shallow Heap : ํ๋์ ๊ฐ์ฒด๊ฐ ์ฐจ์งํ๋ ์์ญ
- Retained Heap : ํด๋น ๊ฐ์ฒด์ ๋ฉ๋ชจ๋ฆฌ์ ํด๋น ๊ฐ์ฒด๊ฐ ์ฐธ์กฐํ๋ ๊ฐ์ฒด๋ค์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํฌํจํ ์์ญ. Memory Leak์ ๋ถ์ํ ๋ ํนํ ์ ๊ฒฝ์จ์ผ ํ ์์ญ
Details
ํ์ ๋ํ ๊ฐ๋ต์ ์ธ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค.
Unreachable Objects Histogram : ํด๋์ค๋ณ๋ก ์์ฑ๋ ๊ฐ์ฒด์ ๋ํ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ค.
Biggest Objects by Retained Size
ํ ์์ญ์ ์์ฑ๋ Objects๋ค ์ค, ๊ฐ์ฅ ๋ง์ ์์ญ์ ์ฐจ์งํ๋ ์ฃผ์ Object์ ๋น์จ์ ํ์ด์ฐจํธ๋ก ํ์ํ๋ค.
์ฐ์ธก์ ์งํ ํ๋์ ์์ญ์ ์ฐํด๋ฆญํ ํ List Objects -> with outgoing references๋ฅผ ํด๋ฆญํ๋ฉด
์ฝ๋์์ ์์ฑํ๋ HashMap ๋ ธ๋๊ฐ ์ฝ 5,000๊ฐ ์์ฑ๋์ด ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
Actions
์์ฑ๋ Object๋ค์ ๋ํ ์ธ๋ถ ๋ด์ญ์ ๋ณด์ฌ์ค๋ค.
Histogram : ํ ์์ญ์ ์์ฑ๋ ๊ฐ์ฒด ํ์ ์ ๋ฐ๋ฅธ ๊ฐ์ฒด์ ์๋ฅผ ํ์.
Dominator Tree : ์์ฑ๋ ๊ฐ์ฒด์ ๋ํ ์ธ๊ณผ๊ด๊ณ(์์ฑ๊ด๊ณ)๋ฅผ ๊ณ์ธต ํํ๋ก ํ์ํ๋ฉฐ ์์ฑ๋ ๊ฐ์ฒด์ ํฌ๊ธฐ ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ ์ %๋ฅผ ํ์ํ๋ค.
์๋ Reports์ LeakSuspect๋ฅผ ํตํด ํ ๋ฉ๋ชจ๋ฆฌ ์ํฉ์ ๋ํ ํํธ๋ฅผ ์ป์ ํ, Dominator Tree์์ ์์ธํ๊ฒ ์ดํด๋ณด๋ ๊ฒ์ด ํจ์จ์ ์ด๋ค.
์ฝ๋์์ ์์ฑํ๋ HashMap ๋ ธ๋์ ๋ํ ์์ธํ ์ ๋ณด๋ฅผ ํ์ธํ ์ ์๋ค.
Top Consumers : ๊ฐ์ฅ ๋ง์ด ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ์ค์ฌ์ผ๋ก ์ธ๋ณด ์ ๋ณด ํ์ํ๋ค.
Duplicate Classes : ์ค๋ณต ์์ฑ๋ ํด๋์ค์ ๋ํ ์ ๋ณด๋ฅผ ํ์ํ๋ค.
Reports
ํ ์์ญ์ ๋ํ ๋ถ์ ๋ฆฌํฌํธ๋ฅผ ์ ๊ณตํ๋ค.
LeakSuspect : ๋ฉ๋ชจ๋ฆฌ ๋ฆญ(Leak)์ผ๋ก ์์ฌ๋๋ ๊ฐ์ฒด์ ๋ํ ๋ถ์์ ๋ณด์ฌ์ค๋ค.
์ฝ๋์์ ์์ฑํ๋ HashMap ๋ ธ๋๊ฐ Problem Suspect 1๋ก ์ ์ ๋์ด ์๋จ์ ๋ฑ์ฅํ๋ค.
Top Conponents : ํ ์์ญ์์ ๊ฐ์ฅ ๋ง์ ์์ญ์ ์ฐจ์งํ๋ ๊ฐ์ฒด์ ๋ํ ์ธ๋ถ์ ์ด๊ณ ์ข ํฉ์ ์ธ ๋ถ์์ ๋ณด์ฌ์ค๋ค.
Step By Step
MAT์ ์ด์ฉํ์ฌ Heap Dump๋ฅผ ๋ถ์ํ๋ ์ ์ฐจ ๋ฐ๋ชจ๋ฅผ ์ ๊ณตํ๋ค.