简体   繁体   English

直接分配给Old Generation的巨大对象的大小

[英]Size of Huge Objects directly allocated to Old Generation

Recently I've been reading about object allocations in different generations in Java. 最近我一直在阅读Java中不同代的对象分配。 Most of the times new objects are allocated in Eden (part of Young Generation) and then they're promoted to Old Generation if any of the following criteria are met. 大多数时候,新对象在Eden(Young Generation的一部分)中分配,然后如果满足以下任何条件,它们将被提升为Old Generation。

(1) Object's age reached the tenuring threshold (1)对象的年龄达到了终点
(2) Survivor space (to) is full when objects are being copied from Eden (or) another survivor space(from) (2)当从伊甸园(或)另一个幸存者空间(从)复制对象时,幸存者空间(to)已满

But there's also a special case in which objects are directly allocated in the Old Generation instead of being promoted from the young generation. 但也有一个特殊情况,即在旧世代中直接分配对象,而不是从年轻一代中提升。 This happens when the object that we're trying to create is huge (possibly of the order of few MBs). 当我们尝试创建的对象很大(可能是几MB的数量级)时会发生这种情况。


Is there any way to know the size/limit of the huge/humongous objects? 有没有办法知道巨大/巨大物体的大小/限制? I'm aware of the humongous objects criteria for G1 Garbage Collector. 我知道G1垃圾收集器的巨大对象标准。 I just want to know the size limit before or in Java 6 . 我只想知道Java 6之前或之中的大小限制。

Thanks for your time :) 谢谢你的时间 :)

The maximum size of an object HotSpot JVM may allocate in young generation is nearly as large as the size of Eden (YoungGen minus two Survivor spaces). HotSpot JVM在年轻代中可能分配的对象的最大大小几乎与Eden(YoungGen减去两个Survivor空间)的大小一样大。

That's how the allocation rougly looks like: 这就是分配粗鲁的样子:

  1. Use Thread Local Allocation Buffer (TLAB), if tlab_top + size <= tlab_end 如果tlab_top + size <= tlab_end ,请使用线程本地分配缓冲区( tlab_end
    This is the fastest path. 这是最快的路径。 Allocation is just the tlab_top pointer increment. 分配只是tlab_top指针增量。
  2. If TLAB is almost full, create a new TLAB in Eden and retry in a fresh TLAB. 如果TLAB几乎已满,请在Eden中创建一个新的TLAB,然后在新的TLAB中重试。
  3. If TLAB remaining space is not enough but is still to big to discard, try to allocate an object directly in Eden. 如果TLAB剩余空间不足但仍然要丢弃,请尝试直接在Eden中分配对象。 Allocation in Eden is also a pointer increment ( eden_top + size <= eden_end ) using atomic operation, since Eden is shared between all threads. Eden中的分配也是使用原子操作的指针增量( eden_top + size <= eden_end ),因为Eden在所有线程之间共享。
  4. If allocation in Eden fails, a minor collection typically occurs. 如果Eden中的分配失败,则通常会发生次要收集。
  5. If there is not enough space in Eden even after Young GC, an attempt to allocate directly in Old generation is made. 如果即使在Young GC之后Eden中没有足够的空间,也会尝试直接在Old Generation中进行分配。

You can set the limit by using following flag 您可以使用以下标志设置限制

XX:PretenureSizeThreshold=size

its default value is 0 I assume that by default if you don't set it it doesn't get considered with value= 0 , that means by default there is no maximum value that acts as threshold, by default object gets promoted only based on number of GC survival 它的默认值是0我假设默认情况下如果你没有设置它就不会考虑值= 0 ,这意味着默认情况下没有最大值作为阈值,默认情况下,对象仅基于提升而被提升GC存活数

HotSpot version HotSpot版本

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)

to get all vm options (supported) you can run 获取所有vm选项(支持),您可以运行

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

and then you can refer to hotspot vm option document or google particular option if not listed 然后你可以参考hotspot vm选项文档或google特定选项(如果没有列出)


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

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

outputs: 输出:

$ 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

JVM flags: JVM标志:

-Xms1G -Xmx1G -Xmn500m -XX:PretenureSizeThreshold=100000000 -XX:+PrintGCDetails -Xms1G -Xmx1G -Xmn500m -XX:PretenureSizeThreshold = 100000000 -XX:+ PrintGCDetails

By fixing the young generation size to 500MB, eden comes around 384MB, So any object greater than 384MB goes directly into OldGen and object less than 384MB is allocated in Eden itself. 通过将年轻一代的大小固定为500MB,eden大约为384MB,因此任何大于384MB的对象都会直接进入OldGen,并且在Eden本身中分配的对象少于384MB。 You can find the generation usages below 您可以在下面找到生成用法

byte[] array = new byte[400*1024*1024]; byte [] array = new byte [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 

byte[] array = new byte[300*1024*1024]; byte [] array = new byte [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** 

For 400MB allocation, eden usage is 8% where as old gen usage is 76% For 300MB allocation, eden usage is 88% where as old gen usage is 0% So its clear that all the objects whose size is greater than the eden will be allocated directly into old gen. 对于400MB分配,eden使用率是8%,其中旧的使用率为76%对于300MB分配,eden使用率为88%,而旧的使用率为0%因此很明显所有大小都超过伊甸园的对象将是直接分配到旧的。

Thanks apangin & Jigar for your valuable insights :) 感谢apangin和Jigar的宝贵见解:)
I think -XX:PretenureSizeThreshold is not considered at all. 我认为-XX:根本没有考虑PretenureSizeThreshold。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM