跨越Java Heap的年轻和终身部分的大型数组分配

时间:2011-03-04 19:21:45

标签: java garbage-collection

是否可以跨java堆的年轻和终身区域分配大型数组?

我认为我正在简化这个问题,因为这些地区有自己的子区域。我只想了解单个分配是否可以跨越多个区域(年轻和终身)。如果是,那么如何进行垃圾收集,因为所使用的策略对于不同的区域是不同的(我认为至少在ParallelGC的情况下,不同的收集器用于不同的区域)。

以下是一个示例,以便使问题更加清晰。让我们说-Xms和-Xmx设置为900M,NewRatio(年轻人与终身比率)设置为2.这将导致年轻区域为300M,终身为600M。现在如果我尝试分配一个“新字节[750]”,那么分配就会通过,因为没有一个区域可能有足够的连续空间。

我问这个问题的原因是我遇到了一个问题(OutofMemoryError),它分配了一个大型数组(这在我的代码中实际上是大多数分配),我通过更改-XX:NewRatio来解决它。我的假设是,大阵列肯定会进入终点区域,而我的终身区域至少应该拥有阵列所需的空间。

2 个答案:

答案 0 :(得分:1)

Java数组始终在连续内存中分配。他们不会分手。

新对象总是在年轻一代中分配,如果他们在足够的GC事件中存活下来,则会被转移到终身。因此,请确保您的年轻分配足够大。

如果没有750字节的连续区域,您将无法获得新的字节[750]。

答案 1 :(得分:0)

iluxa的答案不是很正确(或者现在已经过时了)。如果年轻/新一代没有足够的空间,则将在终身/老一代中直接分配。

这是[apangin的答案]中的直接引言

  

这就是分配的样子:

     
      
  1. 如果tlab_top + size <= tlab_end
    ,请使用线程本地分配缓冲区(TLAB)   这是最快的路径。分配只是tlab_top指针的增量。
  2.   
  3. 如果TLAB快满了,请在伊甸园创建一个新的TLAB,然后在一个新的TLAB中重试。
  4.   
  5. 如果TLAB剩余空间不足,但仍要丢弃,请尝试直接在Eden中分配对象。分配在   Eden也是指针增量(eden_top + size <= eden_end)   使用原子操作,因为Eden在所有线程之间共享。
  6.   
  7. 如果在Eden中分配失败,通常会进行次要回收。
  8.   
  9. 如果在年轻的GC之后甚至在Eden中没有足够的空间,则尝试直接在Old generation中进行分配。
  10.   

从彼得·劳瑞(Peter Lawrey)那里,Larger objects can be placed straight into tenured space.