JDK-6880903 : G1: G1 reports incorrect Runtime.maxMemory()
  • Type: Bug
  • Status: Closed
  • Resolution: Fixed
  • Component: hotspot
  • Sub-Component: gc
  • Priority: P2
  • Affected Version: hs17
  • OS: generic
  • CPU: generic
  • Submit Date: 2009-09-10
  • Updated Date: 2013-09-18
  • Resolved Date: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
6u21Resolved 7Fixed
A customer is reporting that G1 reports incorrect (low) Runtime.maxMemory(). Here's the e-mail:

I tried out G1 for the first time today and noticed that it reports a radically smaller value for Runtime.maxMemory() when compared to the same JVM without the G1 collector.  Is that behavior expected?  This was JDK 1.6.0_16 on Win32.  I was planning to use Runtime.maxMemory() to set the capacity for the hard reference queue backing the weak value cache per the thread below.  Is there actually less memory available with G1 or is the reported value wrong, in which case I could add a command line flag to directly specify the desired maximum bytes buffered for bigdata.

Here are the values reported for Runtime.maxMemory()

	maxMemory=1009778688 when no garbage collector options are specified.


	maxMemory=15728640   when -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC is specified.

The other VM options are: -ea -server -Xmx1000m

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/ed52bcc32739

SUGGESTED FIX I'll piggyback a very minor cosmetic change in g1MemoryPool.{hpp,cpp} on this CR.

SUGGESTED FIX This is the behavior before (on my 2G Linux x86 laptop): tonys-laptop:~> java -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -jar ~/Projects/MMTest/dist/MMTest.jar max memory = 33554432 tonys-laptop:~> java -Xms32m -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -jar ~/Projects/MMTest/dist/MMTest.jar max memory = 33554432 This is the behavior after, which seems correct: tonys-laptop:~> java -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -jar ~/Projects/MMTest/dist/MMTest.jar max memory = 524288000 tonys-laptop:~> java -Xms32m -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -jar ~/Projects/MMTest/dist/MMTest.jarVM max memory = 134217728 This is the same app with ParallelScavenge: tonys-laptop:~> java -jar ~/Projects/MMTest/dist/MMTest.jar max memory = 504889344 tonys-laptop:~> java -Xms32m -Xmx128m -jar ~/Projects/MMTest/dist/MMTest.jar max memory = 129302528 This is slightly different to what G1 returns, because ParallelScavenge subtracts the space of the unused survivor from the reserved size. We won't do that in G1.

SUGGESTED FIX Change G1CollectedHeap::max_capacity() to size_t G1CollectedHeap::max_capacity() const { return _g1_reserved.byte_size(); }

EVALUATION The reason for this is that we return the committed size from method G1CollectedHeap::max_capacity(), instead of the reserved size: size_t G1CollectedHeap::max_capacity() const { return _g1_committed.byte_size(); }