United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6880903 G1: G1 reports incorrect Runtime.maxMemory()
JDK-6880903 : G1: G1 reports incorrect Runtime.maxMemory()

Details
Type:
Bug
Submit Date:
2009-09-10
Status:
Closed
Updated Date:
2011-03-08
Project Name:
JDK
Resolved Date:
2011-03-08
Component:
hotspot
OS:
generic
Sub-Component:
gc
CPU:
generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
hs17
Fixed Versions:
hs17 (b06)

Related Reports
Backport:
Backport:

Sub Tasks

Description
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.

vs

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

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

                                    

Comments
SUGGESTED FIX

Change G1CollectedHeap::max_capacity() to

size_t G1CollectedHeap::max_capacity() const {
  return _g1_reserved.byte_size();
}
                                     
2009-11-26
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();
}
                                     
2009-11-26
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.
                                     
2009-11-26
SUGGESTED FIX

I'll piggyback a very minor cosmetic change in g1MemoryPool.{hpp,cpp} on this CR.
                                     
2009-11-26
EVALUATION

http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/ed52bcc32739
                                     
2009-12-04



Hardware and Software, Engineered to Work Together