5

OutOfMemoryError은 새 오브젝트를 작성할 메모리가 힙에 없을 때 발생합니다. 힙에 충분한 메모리가없는 경우 OutOfMemoryError 개체가 만들어집니다. 나는 이것을 이해하려고 애쓰는 중이다.Java에서 작성된 OutOfMemoryError 오브젝트의 위치

+0

우수한 인터뷰 질문 IMO - 그러나 나는 그것을 실패했을 것입니다. 그것을 게시 해 주셔서 감사합니다 – Eugene

답변

4

이것은 기본적으로 JVM에 의해 생성되며 -Xmx 또는 다른 매개 변수에 의해 제한되지 않습니다. 프로그램에 예약 된 힙이 고갈되었으며 JVM에 사용할 수있는 메모리가 소모되지 않습니다.

+0

고마워요. 글쎄, 인터뷰에서 나에게 묻는 인터뷰 질문 중 하나였습니다. – manjosh

+0

사실, [약간 더 복잡해졌습니다] (0120-333-2555) ... – Holger

6

물론 구현에 의존하는 동작입니다. HotSpot은 보통의 할당에서는 액세스 할 수없는 힙 메모리가 있지만 JVM은 OutOfMemoryError을 생성 할 수 있습니다. 그러나 Java는 임의의 수의 스레드를 허용하기 때문에 임의의 수의 스레드가 동시에 벽을 칠 수 있으므로 보장이 없습니다. 그 메모리는 각각에 대해 고유 한 OutOfMemoryError 인스턴스를 구성하기에 충분합니다.

따라서 실제 메모리가 남아 있지 않은 경우에도 오류가 발생할 수 있도록 전체 세션 동안 지속되는 JVM 시작시 긴급 OutOfMemoryError 인스턴스가 생성됩니다. 실제로 메모리가 남아 있지 않으면 서 인스턴스가 모든 스레드에서 오류를 공유하므로이 오류에 스택 추적이 없다는 사실을 알게 될 것입니다.

ConcurrentHashMap<OutOfMemoryError,Integer> instances = new ConcurrentHashMap<>(); 

ExecutorService executor = Executors.newCachedThreadPool(); 
executor.invokeAll(Collections.nCopies(1000,() -> { 
      ArrayList<Object> list = new ArrayList<>(); 
      for(;;) try { 
       list.add(new int[10_000_000]); 
      } catch(OutOfMemoryError err) { 
       instances.merge(err, 1, Integer::sum); 
       return err; 
      } 
     })); 
executor.shutdown(); 
System.out.println(instances.size()+" distinct errors created"); 
instances.forEach((err,count) -> { 
    StackTraceElement[] trace = err.getStackTrace(); 
    System.out.println(err.getClass().getName()+"@"+Integer.toHexString(err.hashCode()) 
     +(trace!=null&&trace.length!=0? " has": " has no")+" stacktrace, used "+count+'x'); 
}); 

-Xmx100Mjdk1.8.0_65에서 실행 반 분을 기다리는 다음 프로그램은 예약 된 메모리가 포함 네 가지 OutOfMemoryError 인스턴스의 구성 (역할을 할 수 있음을 보여주는 나에게

5 distinct errors created 
[email protected] has no stacktrace, used 996x 
[email protected] has stacktrace, used 1x 
[email protected] has stacktrace, used 1x 
[email protected] has stacktrace, used 1x 
[email protected] has stacktrace, used 1x 

했다 메모리는 스택 트레이스를 기록하는 데 필요함) 다른 모든 스레드는 예약 된 공유 인스턴스로 폴백해야했습니다.

숫자는 환경에 따라 다를 수 있습니다.

+0

매우 흥미 롭습니다. 나는 이것에 대해 전혀 몰랐습니다. – Eugene