Recently I've been reading about object allocations in different generations in 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.
(1) Object's age reached the tenuring threshold
(2) Survivor space (to) is full when objects are being copied from Eden (or) another survivor space(from)
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).
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. I just want to know the size limit before or in 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).
That's how the allocation rougly looks like:
tlab_top
+ size
<= tlab_end
tlab_top
pointer increment. eden_top
+ size
<= eden_end
) using atomic operation, since Eden is shared between all threads.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
HotSpot version
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
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
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:
-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. You can find the generation usages below
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];
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.
Thanks apangin & Jigar for your valuable insights :)
I think -XX:PretenureSizeThreshold is not considered at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With