Java로 프로세스를 만들고 1달 내내 잘 굴리다가 (안껐음)
GC가 계속 돌면서 Stop The WORLD가 된 상황에 이게 머선 일인가 싶어서
Heapmemory를 들쎠봤다.
jmap -dump:format=b,file=<filename>-0.hprof <PID>
상기 커맨드로 heapdump를 뜨고 Intellij에 드래그 드랍하면 JVM 메모리가 다뜬다.

GC가 돌면서 뭔가를 못지우고 있으니까 메모리가 100%를 점유하고 그래서 프로세스가 멈춘다고 생각함.

GracefulShutdown을 위해 ShutdownHook을 걸어놨는데, Runtime에서 이 ShutdownHook 쓰레드를 물고 있으니, 생성된 객체가 사라지지 않고 메모리에 계속 남는 상황이었음.
이게 TCP 서버였고, 다른 소켓이 붙을 때 핸들러를 생성하는데, 이 녀석 버퍼에 뭔가가 남아 있는 상태에서 시스템 다운 시그널을 받을 경우 Graceful 다운 시키려고 만든 셧다운 스레드 였는데, 소켓이 해제 됐다가 다시 연결되고 이를 반복하게 될 경우 시스템 다운 시그널도 안받았고, 핸들러의 shutdown 스레드를 Runtime에서 잡고 있으니, 이게 GC가 안쓸고 가는 거였음.
Runtime.getRuntime().addShutdownHook(hook);
소켓 해제 될 때를 close() 메서드를 호출하는 부분이 있는데, 여기에
Runtime.getRuntime().removeShutdownHook(hook);
이런 식으로 Hook을 없애주면 GC가 돌면서 메모리를 잘 없애준다.
문제는 모든 소켓 해지시 저 removeShutdownHook을 호출해줘야 하는데, 설계가 잘못 돼 있다면 여전히 메모리 누수가 발생할거다. 조심히 사용 할 것
암튼 removeShutdownHook을 사용한 후에 강제로 GC를 돌려봄
jcmd <pid> GC.run
상기 커맨드를 사용하면 강제로 GC를 돌린다. 덤프를 다시 뜨든 sysout을 찍든 해서 생성된 객체가 잘 사라졌는지 확인해보자.