JDK-4700099 : JRE1.4.0: maxMemory() returns wrong value in applet
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-06-10
  • Updated: 2002-06-28
  • Resolved: 2002-06-28
Related Reports
Duplicate :  
Description

Name: gm110360			Date: 06/10/2002


FULL PRODUCT VERSION :
No Command Line (using Browser to access Java Applet)
Install Java 1.4.0 Plugin on Windows 2000
Using a browser to access a webpage with an Applet.
The applet has Runtime.getRuntime().maxMemory() calls and outputs values to the
standard out (console).


FULL OPERATING SYSTEM VERSION : MS Windows 2000


ADDITIONAL OPERATING SYSTEMS : RedHat Linux 7.1



EXTRA RELEVANT SYSTEM CONFIGURATION :
512MB RAM
1.2GHz Pentium III

A DESCRIPTION OF THE PROBLEM :
Console output from a Java Applet with calls to
Runtime.getRuntime().maxMemory() return incorrect values.

Using Sun JRE 1.4.0 and configuring the ControlPanel->Java
Plugin 1.4.0 VM Parameters with different parameters,
yields incorrect results.

-Xms -Xmx
VM Parameter   maxMemory()  totalMemory()  freeMemory()
-------------  -----------  -------------  ------------
(none)         163 Meg      17  Meg        7   Meg
128m 256m      327 Meg      130 Meg        113 Meg

With no parameters, the maximum heap size is 64 Meg. This
is true, and my applet throws an OutOfMemory exception at
64 Meg, however the maxMemory always reports 163 Meg.

With -Xms128m -Xmx256m, the maximum heap size is 256 Meg.
This is true, and my applet throws an OutOfMemory exception
at 256 Meg, however the maxMemory always reports 327 Meg.

This is a real problem, since I know of no other way to
query memory bounds. We must have a method to determine how
much memory we can use because out of memory exception
handling is not acceptable way to hanlde program control.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Install Sun Java Plugin 1.4.0
2. Do not set VM parameters
3. Call applet that displays Runtime.getRuntime().maxMemory
() and see that value is 163 Meg (approx 163*1024000
bytes). Which is wrong. The maxMemory() with no options, is
64 Meg.
4. Try different -Xms -Xmx values and do step 3 and record
results. (ie. -Xms128m -Xmx256m)


EXPECTED VERSUS ACTUAL BEHAVIOR :
Runtime.getRuntime().maxMemory() should return the upper
bounds of the memory available to this runtime.

Even though the you are not gauranteed the amount of memory
you request in -Xmx<ZZZ>m, you still trust the user has set
this amount for a reason. In addition, the value can be
larger than physical memory (ie. -Xmx1000m) and should
work, assuming there is physical disk space to accomdate
the paging needs for the additional memory needed beyond
physical memory (ie. you have 256M RAM, you set -Xmx1000m,
paging to disk begins after the 256M RAM is exausted).

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Use simple print statements in your applet to display runtime memory:

public void printRT() {
   System.out.println("Max: " + Runtime.getRuntime().maxMemory() );
   System.out.println("Total: " + Runtime.getRuntime().totalMemory() );
   System.out.println("Free: " + Runtime.getRuntime().freeMemory() );
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Use try/catch statements on memory intensive areas to catch
OutOfMemoryError exceptions. In addition, it takes memory
to handle exceptions. In the exception handling, you must
purge some or all items using the memory. Then what? Find
some other creative way to try again (what originally
failed) using less memory, not an easy task. No way to do
this everywhere as everything uses memory, plus it's very
ugly and difficult to maintain. Without "knowing" the
memory bounds in an applet, you cannot look ahead to
predict if you have enough memory to do what the user
wants. For instance, you need to load 200 images into
memory and they are all 1024x1000 and you're trying to fit
them on a 1024x1000 canvas. Can your applet calculate if
there is enough room? No. You can do the math, you know you
will need at least 1Meg per image just for the pixels and
some fixed value for the objects you create for the image
objects per image. You have to start one by one, if they
all load, great. If not, you ran out of memory and you
start over loading them into a different size panel, or
something. Not very elegant.
(Review ID: 146167) 
======================================================================

Comments
EVALUATION Do you experience this same behavior if you run you code as an application instead of an applet? ###@###.### 2002-06-11 This does not appear to be a plugin issue. With the following test case I can cause the "java" command to report a "wrong" value. The VM seems to reserver an additional 64M for it's own use that it reports in the "maxMemory()" return, but that the application has no access to. public class test { public static void main(String args[]) { memoryhog[] mh = new memoryhog[1024]; for(int i=0;i<1024;i++) { long max = Runtime.getRuntime().maxMemory(); long tot = Runtime.getRuntime().totalMemory(); long free = Runtime.getRuntime().freeMemory(); System.out.println(i); System.out.println("Max: " + max + " : " + (max/1024)/1024); System.out.println("Total: " + tot + " : " + (tot/1024)/1024); System.out.println("Free: " + free + " : " + (free/1024)/1024); mh[i] = new memoryhog(); System.out.println(""); } } } class memoryhog { int[] memory; memoryhog() { memory = new int[1024*1024]; } } ###@###.### 2002-06-11 ---------------------------------------------------------------- Mark says that "the rough intent" was to return the value of -Xmx, though that's not what the spec says. What we are returning is the "reserved" space for the heap, which includes a survivor space and the permanent generation that are part of the collected heap, but not available for Java objects. We should just return _max_heap_size or MaxHeapSize, or maybe the max of those. ###@###.### 2002-06-11 ----------------------------------------------------------------
11-06-2002