이 포스팅의 코드 및 정보들은 강의를 들으며 정리한 내용을 토대로 작성한 것입니다.
PermGen
이라고 불리는 곳은 Permanent Generation
이라고 불리던 곳이며, 클래스 정보(메타데이터)를 담아뒀던 저장소이자 메모리 공간이었다.
그래서 클래스를 로딩할 때, 클래스의 이름/static 멤버들 등의 정보들을 쭉 담으며, 클래스를 많이 쓰면 쓸수록 그 공간의 데이터가 쌓인다.
PermGen 이라는 공간이 원래는 Heap 영역의 일부였다. Heap영역에서는 Java에서 JVM 안에 Runtime Data Area 안에 위치하여 메모리 공간을 관리한다. 또한 내부에는 Young Generation/Old Generation이 들어있다.
OS가 제공하는 메모리는 Native Memory라고 불리며, 그 위에 Java 명령어를 실행해서 어떤 프로그램이 실행되면 JVM이 관리하는 메모리 영역 중 Heap이라는 영역이 있다.
Heap 영역에는
Java 8 이후에는 Heap에 있던 PermGen 영역이 없어지고, Heap에는 Young Generation,Eden과 Old Generation 영역만 남게 된다.
사라진 PermGen은 Native Memory에 Metaspace
라는 이름으로 자리잡게 된다.
이 Metaspace는 PermGen과는 비슷하게 초기 사이즈는 정해져 있지만 고정된 사이즈가 없다.
Metaspace의 사이즈에 대해서는 걱정할 필요는 없지만 모니터링은 해봐야한다. 너무 지나치게 늘어나면, 필요한 만큼 기본값이 늘어나 OS에 있는 Native Memory가 차게 된다.
꽉 차면 전체 서버가 죽게 된다. 즉, 서버의 메모리가 부족해지는 상황이 발생하는 것이다.
최소한으로 해줘야 하는 것은 Metaspace의 최댓값을 설정하는 것이다.
-XX:MaxMetaspaceSize=N
이 옵션으로 Metaspace의 사이즈를 지정해줄 수 있다.만약 중간에 사이즈를 조금 시작했다가 늘리는, Operation 자체도 줄이고 싶다면 애쵸에 -XX:MetaspaceSize=N
를 -XX:MaxMetaspaceSize=N
만큼의 값을 주면 된다.
그러나 효율적으로 쓰려면 모니터링을 해서 Jstat이라는 커맨드가 제공하는 옵션을 사용하면 이걸로도 Metaspace에 얼만큼의 Memory를 쓰고 있는지에 대한 모니터링이 가능해진다.
그런 것들을 모니터링해서 사이즈를 설정할 적절한 값을 찾으면 된다. 값을 찾아서 그걸 가지고 Max로 정해놓으면 감지할 수 있다.
Max값이 딱 차면서 GC도 감당하지 못하는 경우는 어딘가에서 누수가 있다는 것이다.
어디선가 클래스를 만들어내고, 로딩하는 곳에서 무슨 일이 있으면 그걸 찾아서 해결해야 한다.
JVM의 여러 메모리 영역 중에서 PermGen 메모리 영역이 없어지고 Metaspace 영역이 생겼다.
PermGen
Metaspace