Java 프로세스를 구성하는 요소를 고려하십시오.
당신은이 :
- 는 JVM (C 프로그램)
- JNI 데이터를
- 자바 바이트 코드
- Java 데이터
특히
, 그들은 모두 C에 살고 힙 (JVM 힙은 자연스럽게 C 힙의 일부 임).
Java 힙에서 Java 힙은 Java 바이트 코드 및 Java 데이터입니다. 그러나 Java 힙에는 "여유 공간"도 있습니다.
일반적인 (즉 Sun) JVM은 필요에 따라 Java 힙만 커지 만 축소하지는 않습니다. 정의 된 최대 값 (-Xmx512M)에 도달하면 성장을 멈추고 남아있는 것이 무엇이든 처리합니다. 최대 힙이 모두 소모되면 OutOfMemory 예외가 발생합니다.
Xmx512M 옵션이 수행하지 않는 것은 프로세스의 전체 크기를 제한하는 것입니다. 프로세스의 Java 힙 부분 만 제한합니다.
예를 들어 10MB의 Java 힙을 사용하지만 500MB의 C 힙을 할당하는 JNI 호출을 호출하는 고안된 Java 프로그램을 사용할 수 있습니다. Java 힙 크기가 작더라도 프로세스 크기가 얼마나 큰지 알 수 있습니다. 또한 새로운 NIO 라이브러리를 사용하면 힙 외부에서도 메모리를 연결할 수 있습니다.
Java GC가 일반적으로 "콜렉터 복사 중"이라는 점을 고려해야합니다. 즉, 수집중인 메모리에서 "실제"데이터를 가져와 다른 메모리 섹션에 복사한다는 의미입니다. 적어도 Xmx 매개 변수의 관점이 아닌 HEAP의 일부가 아닌이 빈 공간. 그것은 마치 "새로운 힙"과 같으며 복사 후에는 힙의 일부가됩니다 (이전 GC가 다음 공간으로 사용됨). 512MB 힙을 가지고 있고 510MB에 있다면 Java는 라이브 데이터를 어느 곳에서나 복사 할 것입니다. 순진한 생각은 다른 큰 열린 공간 (500 + MB와 같은)에있을 것입니다. 귀하의 모든 데이터가 "살아"있다면, 복사 할 수있는 큰 덩어리가 필요합니다.
따라서 극단적 인 경우에는 특정 힙 크기를 처리하기 위해 시스템의 여유 메모리를 두 배로 늘려야합니다. 512MB 힙의 경우 최소 1GB.
실제로는 그렇지 않으며 메모리 할당 등은 그보다 복잡하지만 힙 복사본을 처리하기 위해서는 많은 양의 여유 메모리가 필요하므로 전체 프로세스 크기에 영향을 미칩니다.
마지막으로, JVM은 rt.jar 클래스에서 시작을 쉽게하기 위해 VM에 매핑하는 것과 같은 일을 즐깁니다. 그것들은 읽기 전용 블록으로 매핑되고 다른 자바 프로세스에서 공유 될 수 있습니다. 이러한 공유 페이지는 실제 메모리 (가상 메모리의 마술)를 한 번만 소비하더라도 모든 Java 프로세스에 "계산"됩니다.
이제 프로세스가 계속 커지는 이유에 대해 Java OOM 메시지를 전혀 알지 못하면 누수가 Java 힙에 있지 않다는 것을 의미합니다. 그렇다고해서 다른 것 JRE 런타임, 타사 JNI 라이브러리, 원시 JDBC 드라이버 등).