直接分配给旧一代的巨大对象的大小

最近,我一直在阅读有关Java中不同代的对象分配的信息。大多数情况下,新对象被分配在伊甸园(年轻一代的一部分),然后如果满足以下任何条件,它们就会被提升为旧一代。

(1)物体的年龄达到延长阈值
(2) 当物体从伊甸园(或)另一个幸存者空间(从)复制时,幸存者空间(到)已满

但也有一种特殊情况,即对象直接分配给老一代,而不是从年轻一代晋升。当我们试图创建的对象很大(可能只有几MB)时,就会发生这种情况。


有没有办法知道巨大/巨型物体的大小/极限?我知道G1垃圾收集器的大量对象标准。我只想知道Java 6之前或Java 6中的大小限制。

感谢您抽出宝贵时间:)


答案 1

HotSpot JVM在年轻一代中可能分配的最大大小几乎与Eden的大小一样大(YoungGen减去两个幸存者空间)。

这就是分配的样子:

  1. 使用线程本地分配缓冲区 (TLAB),如果 + <=
    这是最快的路径。分配只是指针增量。tlab_topsizetlab_endtlab_top
  2. 如果 TLAB 几乎已满,请在伊甸园中创建一个新的 TLAB,然后在新的 TLAB 中重试。
  3. 如果 TLAB 剩余空间不够,但仍然要丢弃,请尝试直接在 Eden 中分配对象。Eden 中的分配也是使用原子操作的指针增量 ( + <=),因为 Eden 在所有线程之间共享。eden_topsizeeden_end
  4. 如果 Eden 中的分配失败,通常会进行次要收集。
  5. 如果即使在年轻GC之后,伊甸园中也没有足够的空间,则尝试直接在老一代中分配。

答案 2

您可以使用以下标志设置限制

XX:PretenureSizeThreshold=size

它的默认值是我假设,默认情况下,如果您不设置它,则不会考虑value=,这意味着默认情况下没有充当阈值的最大值,默认情况下,对象仅根据GC生存的数量进行升级00

热点版

java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

获取可以运行的所有 vm 选项(受支持)

java -XX:+PrintVMOptions -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal  -version

然后,您可以参考热点vm选项文档或谷歌特定选项(如果未列出)


byte[] array = new byte[300*1024*1024];

for(MemoryPoolMXBean memoryPoolMXBean: ManagementFactory.getMemoryPoolMXBeans()){
    System.out.println(memoryPoolMXBean.getName());
    System.out.println(memoryPoolMXBean.getUsage().getUsed());
}

输出:

$ java -Xmx1500m -Xms1500m -Xmn500m -XX:PretenureSizeThreshold=100000000 -XX:+PrintGCDetails JVMMemoryInspection
Code Cache
393664
PS Eden Space
330301752
PS Survivor Space
0
PS Old Gen
0
PS Perm Gen
2749520