当前位置: 首页 > 知识库问答 >
问题:

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

景俊语
2023-03-14

最近我一直在阅读Java不同世代的对象分配。大多数时候,新对象在伊甸园(年轻一代的一部分)中分配,然后如果满足以下任何标准,它们就会晋升为老一代。

(1) 当从伊甸园(或)另一个幸存者空间(从)复制对象时,对象的年龄已达到寿命阈值
(2)幸存者空间(到)已满

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

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

感谢您抽出时间:)

共有3个答案

梁才
2023-03-14

JVM标志:

-Xms1G-Xmx1G-Xmn500m-XX:PreforureSizeThreshold=100000000-XX:PrintGCDetails

通过将年轻一代的大小固定为500MB,eden大约有384MB,因此任何大于384MB的对象都直接进入OldGen,而小于384MB的对象则在eden中分配。你可以在下面找到这一代人的用法

字节[]数组=新字节[400*1024*1024];

PSYoungGen      total 448000K, used 30720K  
    eden space 384000K, 8% used  
    from space 64000K, 0% used  
    to   space 64000K, 0% used      
 ParOldGen       total 536576K, used 409600K  
   object space 536576K, 76% used 

字节[]数组=新字节[300*1024*1024];

 PSYoungGen      total 448000K, used 337920K  
  eden space 384000K, 88% used  
  from space 64000K, 0% used  
  to   space 64000K, 0% used  
 ParOldGen       total 536576K, used 0K 
  object space 536576K, **0% used** 

对于400MB分配,eden使用率为8%,而旧gen使用率为76%对于300MB分配,eden使用率为88%,而旧gen使用率为0%因此很明显,所有大小大于eden的对象都将直接分配到旧gen中。

谢谢阿潘金

公冶安怡
2023-03-14

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

XX:PretenureSizeThreshold=size

它的默认值是0我假设默认情况下,如果您不设置它,它不会被考虑为value=0,这意味着默认情况下没有充当阈值的最大值,默认情况下,对象仅根据GC存活的数量得到提升

热点版本

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

然后你可以参考热点虚拟机选项文档或谷歌特定选项(如果没有列出)

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
胥康安
2023-03-14

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

这就是分配rougly的样子:

  1. 使用线程本地分配缓冲区(TLAB),如果tlab_topsize
 类似资料:
  • 我有这个程序: 我期望看到的是在年轻一代中创建整数对象,其中一些对象添加到转移到老一代的链表中。所以我希望年轻一代的GC能够始终如一地发生,对象被移动到生存空间,然后再从那里移动到老一代。但我发现的是,老一代的GC一直在发生,年轻一代的GC根本没有发生。这是JVM正在做的某种优化吗?在旧代中直接创建对象的地方?正如您在下图中看到的,年轻的gc只发生了两次,而老的gc发生了41次。仅旧代GC 接下来

  • 问题内容: 我希望能够直接调用分配给对象属性的闭包,而无需将闭包重新分配给变量然后再调用它。这可能吗? 下面的代码不起作用,并导致。 问题答案: 从PHP7开始,您可以 或使用Closure ::call(),尽管不适用于。 在PHP7之前,您必须实现magic 方法来拦截调用并调用回调(当然不可能,因为您无法添加该方法) 请注意,您不能做 在体内,因为这会触发无限循环。

  • 我正在为max分配8GB内存给Java编写的应用程序。它会内存溢出。我相信年轻一代总是比默认情况下的老一代小(堆的1/4)。而Eden/幸存者1,2在年轻一代内部。我相信在Eden空间中创建了新对象。 即使老一代还没有满,但年轻一代已经完全满了,java应用程序还是会耗尽内存吗? 如果短寿命的对象比长寿命的对象多,那么可以为年轻一代分配更多内存,或者至少将堆的50%分配给年轻一代吗?或者,由于jv

  • 问题内容: 是否将“静态最终”直接分配给年轻一代或老一代或烫发一代?(我猜想在我认为的时间内,它很可能会降落到旧的gen中。)如果在perm gen中分配了它,那么当在Perm Gen中进行类卸载时,是否会收集垃圾? 问题答案: 是否将“静态最终”直接分配给年轻一代或老一代或烫发一代? 变量引用的对象将根据与其他任何对象相同的规则进行分配。它最有可能在年轻一代或老一代中分配(如果它很大,并且适用某

  • 问题内容: 我多次听说,在实例化对象时应该执行以下操作: “接口”名称=新的“类”(); 例如,针对实现的类链表: 实现许多接口,包括队列,双端队列等。上面的代码和 要么 为什么必须同时指定两次类型?似乎多余,但oracledocs似乎没有提及。 问题答案: 在Java 7中是多余的。可以将其重写为。 你想写类似的原因: 如果您改变主意,则可以为您提供以后更改数据收集的自由。这样,您的代码将更加灵

  • 我的问题是: > 如何使其与较大的文件一起工作? 有什么办法能让它快一点吗? 我的电脑有8GB的RAM,运行64位Windows 7,处理器是3.40GHz(不确定你需要什么信息)。