ParallelScavenge's heap size settings are initialized in class GenerationSizer : public TwoGenerationCollectorPolicy
. And it goes all the way up, to CollectorPolicy::initialize_size_info()
, where it does a set_max_heap_byte_size(align_size_up(MaxHeapSize, max_alignment()));
.
size_t GenCollectorPolicy::compute_max_alignment() {
// The card marking array and the offset arrays for old generations are
// committed in os pages as well. Make sure they are entirely full (to
// avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
// byte entry and the os page size is 4096, the maximum heap size should
// be 512*4096 = 2MB aligned.
size_t alignment = GenRemSet::max_alignment_constraint(rem_set_name());
// Parallel GC does its own alignment of the generations to avoid requiring a
// large page (256M on some platforms) for the permanent generation. The
// other collectors should also be updated to do their own alignment and then
// this use of lcm() should be removed.
if (UseLargePages && !UseParallelGC) {
// in presence of large pages we have to make sure that our
// alignment is large page aware
alignment = lcm(os::large_page_size(), alignment);
}
return alignment;
}
uintx GenRemSet::max_alignment_constraint(Name nm) {
switch (nm) {
case GenRemSet::CardTable:
return CardTableRS::ct_max_alignment_constraint();
default:
guarantee(false, "Unrecognized GenRemSet type.");
return (0); // Make Windows compiler happy
}
}
static uintx ct_max_alignment_constraint() {
return CardTableModRefBS::ct_max_alignment_constraint();
}
uintx CardTableModRefBS::ct_max_alignment_constraint() {
return card_size * os::vm_page_size();
}
enum SomePublicConstants {
card_shift = 9,
card_size = 1 << card_shift,
card_size_in_words = card_size / sizeof(HeapWord)
};
// on Linux
int os::vm_page_size() {
// Seems redundant as all get out
assert(os::Linux::page_size() != -1, "must call os::init");
return os::Linux::page_size();
}
void os::init(void) {
// ...
Linux::set_page_size(sysconf(_SC_PAGESIZE));
if (Linux::page_size() == -1) {
fatal(err_msg("os_linux.cpp: os::init: sysconf failed (%s)",
strerror(errno)));
}
init_page_sizes((size_t) Linux::page_size());
// ...
}
So the max heap size in my environment is 2MB aligned.
$ java -Xms2m -Xmx2m -XX:PermSize=1m -XX:+PrintCommandLineFlags
-XX:InitialHeapSize=2097152 -XX:MaxHeapSize=2097152 -XX:ParallelGCThreads=4 -XX:PermSize=1048576 -XX:+PrintCommandLineFlags -XX:+UseCompressedOops -XX:+UseParallelGC
$ java -Xms2m -Xmx2m -XX:PermSize=1m -XX:+PrintGCDetails
gives:
Heap
PSYoungGen total 2368K, used 188K [0x00000000ffd60000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 9% used [0x00000000ffd60000,0x00000000ffd8f078,0x00000000fff60000)
from space 320K, 0% used [0x00000000fffb0000,0x00000000fffb0000,0x0000000100000000)
to space 320K, 0% used [0x00000000fff60000,0x00000000fff60000,0x00000000fffb0000)
PSOldGen total 768K, used 0K [0x00000000ff800000, 0x00000000ff8c0000, 0x00000000ffd60000)
object space 768K, 0% used [0x00000000ff800000,0x00000000ff800000,0x00000000ff8c0000)
PSPermGen total 2368K, used 2316K [0x00000000fa600000, 0x00000000fa850000, 0x00000000ff800000)
object space 2368K, 97% used [0x00000000fa600000,0x00000000fa843290,0x00000000fa850000)
The heap layout is:
0x00000000fa600000 <- PSPermGen -> 0x00000000ff800000 <- PSOldGen -> 0x00000000ffd60000 <- PSYoungGen -> 0x0000000100000000
That's 8MB of Java heap (young: 2.625MB, old: 5.375MB), even though -Xmx is 2m; and 82m of PermGen, totaling 90MB of GC heap. What?
$ java -version
java version "1.6.0_25-ea-fastdebug"
Java(TM) SE Runtime Environment (build 1.6.0_25-ea-fastdebug-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.0-b10-fastdebug, mixed mode)
$ java -Xmx2m -Xms2m -XX:PermSize=1m -XX:+TracePageSizes -XX:+PrintCommandLineFlags -XX:+PrintGCDetails
VM option 'PermSize=1m'
VM option '+TracePageSizes'
VM option '+PrintCommandLineFlags'
VM option '+PrintGCDetails'
-XX:InitialHeapSize=2097152 -XX:MaxHeapSize=2097152 -XX:ParallelGCThreads=4 -XX:PermSize=1048576 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+TracePageSizes -XX:+UseCompressedOops -XX:+UseParallelGC
code heap: min=2555904 max=50331648 pg_sz=4096 base=0x00002aaaab026000 size=50331648
ps heap raw: 1024,83968 768,5504 1280,2688 92160
ps heap rnd: 1024,83968 768,5504 1280,2688 92160
ps perm: min=1048576 max=85983232 pg_sz=4096 base=0x00000000fa600000 size=85983232
ps main: min=2097152 max=8388608 pg_sz=4096 base=0x00000000ff800000 size=8388608
card table: min=184321 max=184321 pg_sz=4096 base=0x00002aaaae0e6000 size=188416
Heap
PSYoungGen total 2368K, used 188K [0x00000000ffd60000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 9% used [0x00000000ffd60000,0x00000000ffd8f0d0,0x00000000fff60000)
from space 320K, 0% used [0x00000000fffb0000,0x00000000fffb0000,0x0000000100000000)
to space 320K, 0% used [0x00000000fff60000,0x00000000fff60000,0x00000000fffb0000)
PSOldGen total 768K, used 0K [0x00000000ff800000, 0x00000000ff8c0000, 0x00000000ffd60000)
object space 768K, 0% used [0x00000000ff800000,0x00000000ff800000,0x00000000ff8c0000)
PSPermGen total 2560K, used 2525K [0x00000000fa600000, 0x00000000fa880000, 0x00000000ff800000)
object space 2560K, 98% used [0x00000000fa600000,0x00000000fa8777a8,0x00000000fa880000)
static void trace_gen_sizes(const char* const str,
size_t pg_min, size_t pg_max,
size_t og_min, size_t og_max,
size_t yg_min, size_t yg_max)
{
if (TracePageSizes) {
tty->print_cr("%s: " SIZE_FORMAT "," SIZE_FORMAT " "
SIZE_FORMAT "," SIZE_FORMAT " "
SIZE_FORMAT "," SIZE_FORMAT " "
SIZE_FORMAT,
str, pg_min / K, pg_max / K,
og_min / K, og_max / K,
yg_min / K, yg_max / K,
(pg_max + og_max + yg_max) / K);
}
}
$ java -Xmx2m -Xms2m -XX:PermSize=1m -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal | grep MaxHeapSize
-XX:InitialHeapSize=2097152 -XX:MaxHeapSize=2097152 -XX:ParallelGCThreads=4 -XX:PermSize=1048576 -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:+UseCompressedOops -XX:+UseParallelGC
uintx MaxHeapSize := 8388608 {product}
$ java -version
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02, mixed mode)
void TwoGenerationCollectorPolicy::initialize_flags() {
GenCollectorPolicy::initialize_flags();
OldSize = align_size_down(OldSize, min_alignment());
if (NewSize + OldSize > MaxHeapSize) {
MaxHeapSize = NewSize + OldSize;
}
MaxHeapSize = align_size_up(MaxHeapSize, max_alignment());
//...
}
If -Xmx/MaxHeapSize is smaller than the default NewSize + OldSize
, then MaxHeapSize will be expanded.
$ $JAVA_HOME/bin/java -Xmx2m -Xms2m -XX:PermSize=1m -XX:+PrintCommandLineFlags -XX:+PrintGCDetails
-XX:InitialHeapSize=2097152 -XX:MaxHeapSize=2097152 -XX:ParallelGCThreads=13 -XX:PermSize=1048576 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedOops -XX:+UseParallelGC
Thread::create_vm(), after Arguments::parse(), MaxHeapSize=2097152
Thread::create_vm(), before vm_init_globals(), MaxHeapSize=2097152
Thread::create_vm(), after vm_init_globals(), MaxHeapSize=2097152
Thread::create_vm(), before init_globals(), MaxHeapSize=2097152
init_globals(), before universe_init(), MaxHeapSize=2097152
universe_init(), before Universe::initialize_heap(), MaxHeapSize=2097152
Universe::initialize_heap(), before Universe::heap()->initialize(), MaxHeapSize=2097152
ParallelScavengeHeap::initialize(), before new GenerationSizer(), MaxHeapSize=2097152
GenerationSizer(), before initialize_flags(),MaxHeapSize=2097152
NewSize=1363144, OldSize=5452592, MaxHeapSize=2097152
NewSize=1310720, OldSize=5452592, MaxHeapSize=2097152
NewSize=1310720, OldSize=5439488, MaxHeapSize=2097152
MaxHeapSize=6750208
MaxHeapSize=8388608
GenerationSizer(), after initialize_flags(), MaxHeapSize=8388608
ParallelScavengeHeap::initialize(), after new GenerationSizer(), MaxHeapSize=8388608
Universe::initialize_heap(), after Universe::heap()->initialize(), MaxHeapSize=8388608
universe_init(), after Universe::initialize_heap(), MaxHeapSize=8388608
init_globals(), after universe_init(), MaxHeapSize=8388608
Thread::create_vm(), after init_globals(), MaxHeapSize=8388608
Heap
PSYoungGen total 2368K, used 188K [0x00000000ffd60000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 9% used [0x00000000ffd60000,0x00000000ffd8f118,0x00000000fff60000)
from space 320K, 0% used [0x00000000fffb0000,0x00000000fffb0000,0x0000000100000000)
to space 320K, 0% used [0x00000000fff60000,0x00000000fff60000,0x00000000fffb0000)
PSOldGen total 768K, used 0K [0x00000000ff800000, 0x00000000ff8c0000, 0x00000000ffd60000)
object space 768K, 0% used [0x00000000ff800000,0x00000000ff800000,0x00000000ff8c0000)
PSPermGen total 2368K, used 2243K [0x00000000fa600000, 0x00000000fa850000, 0x00000000ff800000)
object space 2368K, 94% used [0x00000000fa600000,0x00000000fa830d40,0x00000000fa850000)