//VM Args:-Xms4m -Xmx4m -XX:+PrintGCDetails @Test publicvoidheapOutOfMomory(){ Byte[] b = new Byte[1*1024*1024]; }
查看打印出来的的GC信息:
1 2 3 4 5 6 7 8 9 10
[GC [PSYoungGen: 2344K->312K(2368K)] 2910K->1477K(5120K), 0.0083535 secs] [Times: user=0.05 sys=0.00, real=0.01 secs] Heap PSYoungGen total 2368K, used 1830K [0x00000000ffd60000, 0x0000000100000000, 0x0000000100000000) eden space 2048K, 74% used [0x00000000ffd60000,0x00000000ffedb9d8,0x00000000fff60000) from space 320K, 97% used [0x00000000fffb0000,0x00000000ffffe010,0x0000000100000000) to space 320K, 0% used [0x00000000fff60000,0x00000000fff60000,0x00000000fffb0000) ParOldGen total 5504K, used 5261K [0x00000000ff800000, 0x00000000ffd60000, 0x00000000ffd60000) object space 5504K, 95% used [0x00000000ff800000,0x00000000ffd23760,0x00000000ffd60000) PSPermGen total 21248K, used 5716K [0x00000000fa600000, 0x00000000fbac0000, 0x00000000ff800000) object space 21248K, 26% used [0x00000000fa600000,0x00000000fab95308,0x00000000fbac0000)
The problem is os::page_size_for_region, in particular the check: if ((region_min_size & mask) == 0 && (region_max_size & mask) == 0)
If page_size_for_region is called with min_region_size and max_region_size that are a multiple of a page size larger than than max_page_size, then page_size_for_region will return that page.
This problem manifests itself on Solaris using large pages. Solaris will use a page size of 2 MB. If -Xmx4m is used, then GenerationSizer::initialize_size_info will call page_size_for_region(4MB, 4MB, 8 /* min_pages*/). Since 4MB is a multiple 2MB, page_size_for_region will return 2MB. The bug is that we ask for at least 8 pages, which would limit the page size to 4MB/8 = 0.5MB (512 KB). Since parallel scavenge needs at least 4 pages, we get a heap size 4 * 2MB = 8MB, even though the user specified -Xmx4m!
// The survivor ratio's are calculated "raw", unlike the // default gc, which adds 2 to the ratio value. We need to // make sure the values are valid before using them. if (MinSurvivorRatio < 3) { MinSurvivorRatio = 3; }