2016-10-12 6 views
6

특정 크기의 메모리를 사용해야하는 프로그램을 작성하려고합니다. 궁금해하는 문제는 실제로 힙에 여유 공간이있을 때 outOfMemory 예외가 발생한다는 것입니다.전체 메모리를 사용할 수 없음

import java.util.Vector; 
import java.lang.*; 

public class MemoryEater1 { 
    public static void main(String[] args) { 
    try { 
     long mb = Long.valueOf(args[0]); 
     Vector v = new Vector(); 
     Runtime rt = Runtime.getRuntime(); 
     while (true) { 
      if (v.size() > 0) { 
       if (((long) v.size())*100 < mb) { 
        System.out.println("total memory: " + rt.totalMemory()/1024/1024); 
        System.out.println("max memory: " + rt.maxMemory()/1024/1024); 
        System.out.println("free memory: " + rt.freeMemory()/1024/1024);       
        System.out.println("Trying to add 100 mb");     
        //100mb 
        byte b[] = new byte[104857600]; 
        v.add(b); 
       } 
      } else { 
       //100mb 
       byte b[] = new byte[104857600]; 
       v.add(b); 
       System.out.println("Added 100 mb");    
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
} 

는 IT 시작 명령 :

java -Xmx4096m MemoryEater1 3000 

출력 :

total memory: 2867 
max memory: 3641 
free memory: 59 
Trying to add 100 mb 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
     at MemoryEater1.main(MemoryEater1.java:18) 

음 최대 메모리 및 총 메모리의 차이는 여기

는 코드 774 메가 바이트, 100 메가 바이트를 더 소비하기에 충분해야하지만, 여전히 오류가 있으며, 심지어 기계 resourc 충분히 충분하다 :

[[email protected] ~]$ free -m 
      total  used  free  shared buffers  cached 
Mem:   15950  3447  12502   0  210  2389 
-/+ buffers/cache:  847  15102 
Swap:   4031 1759218603  8941 

왜 그럴 수 있습니까?

+6

사용 가능한 메모리가 100MB 미만인지 확인 했습니까? – Stephan

+3

큰 배열을 할당 할 때, 방이 남아있을지라도 JVM이 커다란 연속 블록을 찾지 못할 위험이 항상 있습니다. –

+2

@Stephan'totalMemory'가 이미'maxMemory'로 확장 된 경우에만 관련이 있습니다. –

답변

1

하나의 스레드가 메모리를 할당하고 아무것도 회수하지 않기 때문에 조각화되지 않는다고 생각합니다.

비난 할 특정 가비지 수집기는 메모리를 다르게 관리하므로 앱에서 사용할 수 없게됩니다. java -XX:+PrintCommandLineFlags의 출력을 분석하여 어떤 것을 사용하는지 확인할 수 있습니다.

메모리를 다르게 관리하는 G1을 사용할 수 있습니다.

java -Xmx4096m -XX:+UseG1GC MemoryEater1 3000 

또는 세대 크기로 재생합니다. -XX:NewSize 등등.

자세한 내용은 VM options 및 가비지 수집기 알고리즘의 내용을 참조하십시오. [GC 튜닝]

여러 세대의 메모리를 분할하여 사용할 수 없도록 만드는 방법을 간단히 설명합니다 (http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html). Memory layout

+0

그는 큰 배열 중 하나도 범위를 벗어나지 않으므로 가비지 수집을받을 자격이없는 것으로 보입니다. – Brick

+0

그의 코드는 모든 것을 GC의 손에서 지키기위한 디자인입니다. – AxelH

0

기계의 실제 메모리보다 큰 메모리 양에 대해 JVM 플래그를 설정할 수 있습니다. 지금까지 제공된 정보를 사용하면이 배열을 할당 할 실제 메모리가 부족한 것 같습니다. 즉, JVM은 OS에서 더 많은 메모리를 요청하고 OS는 아무 것도 제공하지 않는다고 말합니다.

또 다른 가능성은 질문에 대한 메모에 메모리 조각화 문제가 기록되어 있다는 것입니다. 그러나이 경우 프로그램의 구조 때문에 가능성이 적습니다. 나는 그것이 비록 배제 될 수 있다고 생각하지 않는다.

관련 문제