是否可以跨java堆的年轻和终身区域分配大型数组?
我认为我正在简化这个问题,因为这些地区有自己的子区域。我只想了解单个分配是否可以跨越多个区域(年轻和终身)。如果是,那么如何进行垃圾收集,因为所使用的策略对于不同的区域是不同的(我认为至少在ParallelGC的情况下,不同的收集器用于不同的区域)。
以下是一个示例,以便使问题更加清晰。让我们说-Xms和-Xmx设置为900M,NewRatio(年轻人与终身比率)设置为2.这将导致年轻区域为300M,终身为600M。现在如果我尝试分配一个“新字节[750]”,那么分配就会通过,因为没有一个区域可能有足够的连续空间。
我问这个问题的原因是我遇到了一个问题(OutofMemoryError),它分配了一个大型数组(这在我的代码中实际上是大多数分配),我通过更改-XX:NewRatio来解决它。我的假设是,大阵列肯定会进入终点区域,而我的终身区域至少应该拥有阵列所需的空间。
答案 0 :(得分:1)
Java数组始终在连续内存中分配。他们不会分手。
新对象总是在年轻一代中分配,如果他们在足够的GC事件中存活下来,则会被转移到终身。因此,请确保您的年轻分配足够大。
如果没有750字节的连续区域,您将无法获得新的字节[750]。
答案 1 :(得分:0)
iluxa的答案不是很正确(或者现在已经过时了)。如果年轻/新一代没有足够的空间,则将在终身/老一代中直接分配。
这是[apangin的答案]中的直接引言
这就是分配的样子:
- 如果
tlab_top
+size
<=tlab_end
,请使用线程本地分配缓冲区(TLAB) 这是最快的路径。分配只是tlab_top
指针的增量。- 如果TLAB快满了,请在伊甸园创建一个新的TLAB,然后在一个新的TLAB中重试。
- 如果TLAB剩余空间不足,但仍要丢弃,请尝试直接在Eden中分配对象。分配在 Eden也是指针增量(
eden_top
+size
<=eden_end
) 使用原子操作,因为Eden在所有线程之间共享。- 如果在Eden中分配失败,通常会进行次要回收。
- 如果在年轻的GC之后甚至在Eden中没有足够的空间,则尝试直接在Old generation中进行分配。
从彼得·劳瑞(Peter Lawrey)那里,Larger objects can be placed straight into tenured space.