development

300GB 메모리로 제한되는 64 비트 JVM?

big-blog 2020. 12. 9. 21:06
반응형

300GB 메모리로 제한되는 64 비트 JVM?


최대 1TB의 RAM 공간을 제공 할 수있는 클러스터 컴퓨팅 환경 (CentOS 릴리스 6.2 Final을 실행하는 IBM LSF)에서 Java 애플리케이션을 실행하려고합니다.

최대 300GB의 최대 메모리 (Xmx)로 JVM을 만들 수 있지만 그 이상이 필요합니다 (요청하면 세부 정보를 제공 할 수 있음).

그러나 Xmx 옵션을 사용하여 최대 300GB 이상의 메모리로 JVM을 만드는 것은 불가능한 것 같습니다. 더 구체적으로 말하자면 고전적인 오류 메시지가 표시됩니다.

VM 초기화 중 오류가 발생했습니다.

개체 힙을위한 충분한 공간을 예약 할 수 없습니다.

내 (64 비트) JVM에 대한 세부 정보는 다음과 같습니다.

OpenJDK 런타임 환경 (IcedTea6 1.10.6) (rhel-1.43.1.10.6.el6_2-x86_64)

OpenJDK 64 비트 서버 VM (빌드 20.0-b11, 혼합 모드)

Java 7 64 비트 JVM도 사용해 보았지만 똑같은 문제가 발생했습니다.

또한 HelloWorld.jar를 실행하기 위해 JVM을 만들려고했지만 -Xmx300G 이상을 요청하면 여전히 JVM 생성이 실패하므로 특정 응용 프로그램과 관련이 없다고 생각합니다.


300G 이상의 최대 메모리로 JVM을 만들 수없는 이유를 아는 사람이 있습니까?

누구든지 솔루션 / 해결 방법을 제안 해 주시겠습니까?


몇 가지 가능한 설명을 생각할 수 있습니다.

  • 시스템의 다른 응용 프로그램이 너무 많은 메모리를 사용하여 현재 300Gb를 사용할 수 없습니다 .

  • 프로세스 당 메모리 크기에 대한 리소스 제한이있을 수 있습니다. 을 사용하여이를 확인할 수 있습니다 ulimit. ( 이 버그 에 따라 프로세스 당 리소스 제한으로 인해 JVM이 힙 영역을 할당하는 것을 중지하면 오류 메시지가 표시됩니다.)

  • 이것은 "과도한 커밋"문제 일 수도 있습니다. 예를 들어 응용 프로그램이 가상 환경에서 실행되고 있고 다른 가상 장치와의 경쟁이 너무 심해서 시스템 전체가 수요를 충족 할 수없는 경우입니다.


제안 된 몇 가지 다른 아이디어는 (IMO) 가능성이 낮습니다.

  • JRE를 전환해도 아무런 차이가 없을 것입니다. 특정 64 비트 JVM에서 임의의 메모리 제한을 듣거나 본 적이 없습니다.

  • 연속 메모리 가 충분하지 않기 때문일 가능성은 없습니다 . 연속 된 물리적 메모리는 필요하지 않습니다. 유일한 가능성은 스왑 장치의 연속적인 공간 일 수 있지만 일반적인 Linux OS에서 문제가되는 것은 기억 나지 않습니다.


누구든지 솔루션 / 해결 방법을 제안 해 주시겠습니까?

  • 을 확인합니다 ulimit.

  • malloc많은 메모리 를 시도 하고 실패하기 전에 할당 할 수있는 양을 확인하는 작은 C 프로그램을 작성 하십시오.

  • 시스템 (또는 하이퍼 바이저) 관리자에게 도움을 요청하십시오.


(편집 됨, 스왑 공간에 대한 추가 섹션 참조)

SHMMAX 및 SHMALL

CentOS 를 사용하고 있으므로 Oracle DB 구성에 대해 여기에 설명 된대로 SHMMAXSHMALL커널 설정 에 대해 유사한 문제가 발생할 수 있습니다 . 동일한 링크 아래에 올바른 설정 을 가져오고 설정하는 계산 예가 있습니다.SHMALL

연속적인 기억

특정 사용자는 이미 사용 가능한 연속 메모리가 충분하지 않다고보고했으며 다른 사용자는 관련성이 없다고 말했습니다.

CentOS의 JVM에 연속적인 메모리 블록이 필요한지 확실하지 않습니다. SAS에 따르면 조각난 메모리는 JVM이 큰 최대 Xmx또는 시작 Xms메모리 설정 으로 시작하지 못하게 할 수 있지만 인터넷의 다른 주장은 중요하지 않다고 말합니다. 48GB Windows 워크 스테이션에서 그 주장을 증명하거나 증명하지 않으려 고 노력했지만 초기 및 최대 설정 40GB로 JVM을 시작했습니다. 해당 크기의 연속 블록을 사용할 수는 없지만 메모리 관리가 OS마다 다를 수 있기 때문에 다른 OS의 JVM이 다르게 동작 할 수 있습니다 (예 : Windows는 일반적으로 개별 프로세스의 물리적 주소를 숨 깁니다).

가장 큰 연속 메모리 블록 찾기

사용 /proc/meminfo가능한 가장 큰 연속 메모리 블록을 찾는 데 사용 합니다 VmAllocChunk. 아래의 값을 참조하십시오 . 다음 은 모든 값에 대한 가이드와 설명 입니다. 표시된 값이 300GB보다 작은 경우 값 바로 아래에있는 값을 시도하십시오 VmAllocChunk.

그러나 일반적으로이 숫자는 물리적으로 사용 가능한 메모리보다 높으며 (사용 가능한 가상 메모리 값 이기 때문에 ) 오 탐지를 제공 할 수 있습니다. 예약 할 수있는 값이지만 사용을 시작하면 스와핑이 필요할 수 있습니다. 따라서 MemFreeInactive도 확인해야 합니다. 반대로 전체 목록을보고 300GB를 초과하지 않는 값을 확인할 수도 있습니다.

64 비트 JVM에 대해 확인할 수있는 기타 조정 옵션

300GB에서 메모리 제한 문제가 발생하는 이유를 잘 모르겠습니다. 잠시 동안 나는 당신이 최대 페이지에 도달했을 것이라고 생각했습니다. 기본값 4kB에서는 300GB가 78,643,200페이지를 제공 합니다. 잘 알려진 마법의 숫자처럼 보이지 않습니다. 2^24를 들어가 최대 값 인 경우 16,777,216페이지 또는 64GB가 이론상 할당 가능한 최대 값이어야합니다.

그러나 더 큰 페이지 (즉, 대용량 메모리 Java 애플리케이션의 성능에 더 좋음)가 필요하다는 주장을 위해 사용 및 설정 방법을 설명하는 JBoss의 맨 페이지를 참조 해야 합니다 ( 다시) (후자가 필요한지 확실하지 않습니다).-XX:+UseLargePageskernel.shmmaxvm.nr_hugepagesvm.huge_tlb_shm_group

시스템 스트레스

다른 사람들도 이미 이것을 제안했습니다. 문제가 OS가 아니라 JVM에 있는지 확인하려면 스트레스 테스트를해야합니다. 사용할 수있는 도구 중 하나는 Stresslinux 입니다. 이 자습서 에서는 사용할 수있는 몇 가지 옵션을 찾을 수 있습니다. 특히 관심있는 것은 다음 명령입니다.

stress --vm 2 --vm-bytes 300G --timeout 30s --verbose

해당 명령이 실패하거나 시스템을 잠그면 OS가 해당 양의 메모리 사용을 제한하고 있음을 알 수 있습니다. 성공하면 사용 가능한 메모리를 사용할 수 있도록 JVM을 조정해야합니다.

Apr6 편집 : 스왑 공간 확인

내부 메모리 크기가 매우 큰 시스템이 스왑 공간을 거의 사용하지 않거나 전혀 사용하지 않는 것은 드문 일이 아닙니다. 많은 응용 프로그램에서 이것은 문제가되지 않을 수 있지만 JVM은 사용 가능한 스왑 공간이 요청 된 메모리 크기보다 커야합니다. 이 버그 보고서 에 따르면 JVM은 스왑 공간 자체를 늘리려 고하지만 이 SO 스레드의 일부 답변 이 제안했듯이 JVM이 항상 그렇게 할 수있는 것은 아닙니다.

따라서 현재 사용 가능한 스왑 공간을 확인하고 cat /proc/swaps # free300GB보다 작은 경우이 CentOS 맨 페이지의 지침에 따라 시스템의 스왑 공간을 늘리십시오.

Note 1: we can deduct from bugreport #4719001 that a contiguous block of available swap space is not a necessity. But if you are unsure, remove all swap space and recreate it, which should remove any fragmentation.

Note 2: I have seen several posts like this one reporting 0MB swap space and being able to run the JVM. That is probably due to the fact that the JVM increases the swap space itself. Still doesn't hurt to try to increase the swap space by hand to find out whether it fixes your issue.

Premature conclusion

I realize that non of the above is an out-of-the-box answer to your question. I hope it gives you some pointers though to what you can try to get your JVM working. You might also try other JVM's, if the problem turns out to be a limit of the JVM you are currently using, but from what I have read so far, no limit should be imposed for 64 bit JVM's.

That you get the error right on initialization of the JVM leads me to believe that the problem is not with the JVM, but with the OS not being able to comply to the reservation of the 300GB of memory.

My own tests showed that the JVM can access all virtual memory, and doesn't care about the amount of physical memory available. It would be odd if the virtual memory is lower than the physical memory, but the VmAllocChunk setting should give you a hint in that direction (it is usually much larger).


If you have a look at the FAQ section of Java HotSpot VM, its mentioned that on 64-bit VMs, there are only 64 address bits to work with and hence the maximum Java heap size is dependent on the amount of physical memory & swap space present on the system.

If you calculate theoretically then you can have a memory of 18446744073709551616 MB, but there are above limitation to it.

You have to use -Xmx command to define maximum heap size for JVM, By default, Java uses 64 + 30% = 83.2MB on 64-bit JVMs.

I tried below command on my machine and it looked to work fine.

java -Xmx500g com.test.TestClass

I also tried to define maximum heap in terabytes but it doesn't work.


Run ulimit -a as the JVM Process's user and verify that your kernel isn't limiting your max memory size. You may need to edit /etc/security/limit.conf


According to this discussion, LSF does not pool node memory into a single shared space. You are using something else for that. Read that something's documentation, because it is possible it cannot do what you are asking it to do. In particular, it may not be able to allocate a single contiguous region of memory that spans all the nodes. Usually that's not necessary, as an application will make many calls to malloc. But the JVM, to simplify things for itself, wants to allocate (or reserve) a single contiguous region for the entire heap by effectively calling malloc just once. Or it could be something else related to whatever you are using to emulate a giant shared memory machine.

참고URL : https://stackoverflow.com/questions/22711247/64-bit-jvm-limited-to-300gb-of-memory

반응형