Name: nt126004 Date: 05/16/2002 FULL PRODUCT VERSION : [c:\java\work]java -version java version "1.4.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92) Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode) FULL OPERATING SYSTEM VERSION : Windows 2000 4NT 3.01A Windows NT 5.00 A DESCRIPTION OF THE PROBLEM : The current documentation says: public long maxMemory() Returns the maximum amount of memory that the Java virtual machine will attempt to use. The behaviour described in bug 4391499 shows numbers that appear to be close to what was requested in the -Xmx flag. In that report, the maxMemory numbers seem to increase in 4MB increments. I would have no problem with that. But what I'm seeing is that the maxMemory values are consistently a full 64MB larger than what was requested in -Xmx, but the effective maximum heap size is actually very close the -Xmx value. So I'm left with the conclusion that the maxMemory() method is worthless in practice. Our client/server package needs to determine at runtime if there's enough memory to accept a new connection. I was hoping to use the logical calculation: available = maxMemory - totalMemory - freeMemory. Instead, we're doing this: boolean refuse = false; try { byte[] memoryCheck = new byte[MIN_STARTUP_MEMORY]; } catch (OutOfMemoryError e) { refuse = true; } That seems to be pretty reliable, but it's causing extra GC thrashing that shouldn't be necessary if we had a reliable way to determine the maximum memory. Also see: http://forum.java.sun.com/thread.jsp?forum=31&thread=253517 STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Run the sample program below. EXPECTED VERSUS ACTUAL BEHAVIOR : Given this code: long max = Runtime.getRuntime().maxMemory(); Expected: I would expect max to correspond to the number of bytes specified in the -Xmx command-line parameter, or the default of 67,108,864 bytes if no -Xmx parameter was specified. Actual: Instead, the value returned is consistently 64MB (67,108,864 bytes) more than the -Mmx parameter. This bug can be reproduced always. ---------- BEGIN SOURCE ---------- public class max { public static void main(String[] args) { long max = Runtime.getRuntime().maxMemory(); System.out.println("Runtime.maxMemory(): "+max+" bytes"); System.out.println("Runtime.maxMemory(): "+max/1024/1024+" MB"); long adjusted = max - (64*1024*1024); System.out.println("Adjusted value is "+adjusted+" bytes"); System.out.println("Adjusted value is "+adjusted/1024/1024+" MB"); } } [c:\java\work]java max Runtime.maxMemory(): 134217728 bytes Runtime.maxMemory(): 128 MB Adjusted value is 67108864 bytes Adjusted value is 64 MB [c:\java\work]java -Xmx128m max Runtime.maxMemory(): 201326592 bytes Runtime.maxMemory(): 192 MB Adjusted value is 134217728 bytes Adjusted value is 128 MB [c:\java\work]java -Xmx134217728 max Runtime.maxMemory(): 201326592 bytes Runtime.maxMemory(): 192 MB Adjusted value is 134217728 bytes Adjusted value is 128 MB ---------- END SOURCE ---------- CUSTOMER WORKAROUND : long max = Runtime.getRuntime().maxMemory() - 64*1024*1024; ...but that's obviously not a good long term solution because I have no idea where the 64MB comes from in the first place. (Review ID: 146629) ======================================================================
|