2014-11-02 1 views
0

Java 응용 프로그램 (32 비트 Windows 컴퓨터와 호환되므로 32 비트 JRE를 사용하려는 경우)은 메모리 집약적이므로 JRE를 시작할 때 사용 가능한 최대 메모리 (Xmx 매개 변수 사용).자바 32 비트 윈도우 : JRE를 시작할 때 사용할 수있는 최대 힙을 결정하십시오.

이론적으로 32 비트가 할당 가능한 메모리의 4Gb를 제공하지만 주어진 Windows의 메모리 관리는 사용 가능한 최대 연속 메모리 블록에 의해 더 제한된다는 것을 이해했습니다. 약간의 테스트를 통해 1024MB의 가치가 대부분의 컴퓨터에서 작동 할 가능성이 가장 높은 것으로 나타났습니다. 응용 프로그램을 시작할 때 우리는 지금 사용할 수있는 최대 힙 메모리를 할당 할 가장 좋은 방법으로 찾고

는 : 시행 착오 이외의 다른 방법이있다 (즉, 4기가바이트와 JRE를 실행 한 후 작동까지 감소) ?

또한 우리는 Launch4J를 사용하여 응용 프로그램을 시작합니다. 가능한 가장 큰 힙 메모리를 정의하는 추가 옵션을 제공합니까?

+0

32 비트가 2GiB를 제공합니다. 할당하는 유일한 방법은'-Xmx'를 통해 다른 금액을 할당하려고 시도하는 스크립트를 작성하고 프로세스가 오류 코드와 함께 종료되면 계속 진행하는 것입니다. 최대 메모리를 할당하면 원하지 않는 가상 메모리가 부족하게됩니다. 참고 : 할당 가능한 가장 큰 메모리는 가상 메모리의 최대 연속 블록에 따라 다릅니다. – bestsss

+0

또 하나의주의 사항 : 당신은 자바가 스왑을 사용하기를 원하지 않는다. 스왑을 치는 전체 가비지 콜렉션은 문자 그대로 분이 걸릴 수있다. – bestsss

+0

감사합니다. Launch4J를 사용하여 시험판을 작성하거나 적어도 메모리 문제가 있는지 감지하고 우아한 오류 메시지를 표시하는 방법이 있습니까? – Tom

답변

0

여기 JNI 기반 실행 프로그램에서이 작업을 수행하는 데 사용하는 win32 코드가 있습니다.이 접근법의 원래 영감은 더 이상 찾을 수없는 웹 사이트였습니다. 사용하기에 좋을 것입니다. Launch4J는 다음과 같은 것을 가지고 있습니다 - 그렇지 않은 경우 추가하도록 요청해야합니다 ;-)). 나는 permGenMB에 대해 62를 사용합니다. maxHeapMB는 요청할 최대 크기 (768, 1024)입니다. getMaxHeapAvailable() 함수는 컴퓨터가 실제로 할당 할 수있는 한도 아래의 크기를 반환합니다.

win32는 ~ 3GB의 주소 지정 가능 메모리를 가지고 있지만 큰 용량의 청크를 얻을 수는 없습니다. JVM은 메모리가 단일 할당 가능 블록에 있어야한다고 요구합니다. 컴퓨터의 RAM 용량은 5GB이며, 하지만 가장 큰 오픈 블록에 1GB 만 있으면 JVM에서 얻을 수있는 최대 용량입니다.

static const DWORD NUM_BYTES_PER_MB = 1024 * 1024; 

bool canAllocate(DWORD bytes) 
{ 
    LPVOID lpvBase; 

    lpvBase = VirtualAlloc(NULL, bytes, MEM_RESERVE, PAGE_READWRITE); 
    if (lpvBase == NULL) return false; 

    VirtualFree(lpvBase, 0, MEM_RELEASE); 

    return true; 
} 

int getMaxHeapAvailable(int permGenMB, int maxHeapMB) 
{ 
    DWORD  originalMaxHeapBytes = 0; 
    DWORD  maxHeapBytes = 0; 
    int   numMemChunks = 0; 
    SYSTEM_INFO  sSysInfo; 
    DWORD  maxPermBytes = permGenMB * NUM_BYTES_PER_MB;  // Perm space is in addition to the heap size 
    DWORD  numBytesNeeded = 0; 

    GetSystemInfo(&sSysInfo); 

    // jvm aligns as follows: 
    // quoted from size_t GenCollectorPolicy::compute_max_alignment() of jdk 7 hotspot code: 
    //  The card marking array and the offset arrays for old generations are 
    //  committed in os pages as well. Make sure they are entirely full (to 
    //  avoid partial page problems), e.g. if 512 bytes heap corresponds to 1 
    //  byte entry and the os page size is 4096, the maximum heap size should 
    //  be 512*4096 = 2MB aligned. 

    // card_size computation from CardTableModRefBS::SomePublicConstants of jdk 7 hotspot code 
    int card_shift = 9; 
    int card_size = 1 << card_shift; 

    DWORD alignmentBytes = sSysInfo.dwPageSize * card_size; 

    maxHeapBytes = maxHeapMB * NUM_BYTES_PER_MB + 50*NUM_BYTES_PER_MB; // 50 is an overhead fudge factory per https://forums.oracle.com/forums/thread.jspa?messageID=6463655 (they had 28, I'm bumping it 'just in case') 

    // make it fit in the alignment structure 
    maxHeapBytes = maxHeapBytes + (maxHeapBytes % alignmentBytes); 
    numMemChunks = maxHeapBytes/alignmentBytes; 
    originalMaxHeapBytes = maxHeapBytes; 

    // loop and decrement requested amount by one chunk 
    // until the available amount is found 
    numBytesNeeded = maxHeapBytes + maxPermBytes; 
    while (!canAllocate(numBytesNeeded) && numMemChunks > 0) 
    { 
     numMemChunks --; 
     maxHeapBytes = numMemChunks * alignmentBytes; 
     numBytesNeeded = maxHeapBytes + maxPermBytes; 
    } 

    if (numMemChunks == 0) return 0; 

    // we can allocate the requested size, return it now 
    if (maxHeapBytes == originalMaxHeapBytes) return maxHeapMB; 

    // calculate the new MaxHeapSize in megabytes 
    return maxHeapBytes/NUM_BYTES_PER_MB; 
} 
관련 문제