2017-09-19 40 views
5

当堆没有足够的内存来创建新对象时会发生OutOfMemoryError。如果堆没有足够的内存,则创建对象的位置在哪里。我想了解这一点,请告知。Java中创建的OutOfMemoryError对象在哪里

+0

优秀的面试问题国际海事组织 - 但我会失败。感谢您发布它 – Eugene

回答

4

它由JVM本地生成,不受-Xmx或其他参数的限制。 程序保留的堆已耗尽,而不是JVM的可用内存。

+0

谢谢。那么这是面试中面试问题中的一个。 – manjosh

+0

其实,[它稍微复杂](https://stackoverflow.com/a/46298757/2711488)... – Holger

6

当然,这是一个依赖于实现的行为。 HotSpot有一些堆内存不能用于普通的分配,JVM可以用来构造一个OutOfMemoryError英寸。但是,由于Java允许任意数量的线程,任意数量的线程可能同时撞墙,所以没有保证该存储器足够用于为它们中的每一个构建不同的OutOfMemoryError实例。

因此,在贯穿整个会话的JVM启动时创建一个紧急情况OutOfMemoryError实例,以确保即使没有剩余内存也能抛出错误。因为所有遇到错误的线程都会共享实例,而实际上没有剩余内存,所以您将通过这个错误将没有堆栈跟踪的事实来识别这个无关的条件。

下面的程序jdk1.8.0_65下运行与-Xmx100M

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'); 
}); 

,等待半分钟给我

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 

表示保留的内存可以成为四个不同OutOfMemoryError实例的建设(包括内存需要记录他们的堆栈跟踪),而所有其他线程必须回退到保留的共享实例。

当然,不同环境下的数字可能会有所不同。

+0

非常有趣,我不知道这个 – Eugene