-
Bug
-
Resolution: Fixed
-
P3
-
1.0, 2.0, 1.3.0
-
1.1
-
generic
-
generic
Name: dkC59003 Date: 06/23/99
The displayed below program allocates millions of tiny instances of the
class Object just trying to provoke OutOfMemoryError, and by the way checks
the time elapsed to allocate each of the Object instances.
When heap is almost exhausted, HotSpot seems too eager to allocate the last
available bytes. Following is the program output showing that JDK 1.3-H
(equipped with HotSpot 1.3 Client beta-H) spends more than 5 minutes to
allocate few tiny objects:
>>>> D:\jdk1.3H\bin\java except001
pool[3313812]=new Object(); // elapsed 2.704s
pool[3346883]=new Object(); // elapsed 1.061s
pool[4133226]=new Object(); // elapsed 4.316s
pool[4133227]=new Object(); // elapsed 65.835s
pool[4133228]=new Object(); // elapsed 65.764s
pool[4133229]=new Object(); // elapsed 65.785s
pool[4133230]=new Object(); // elapsed 65.764s
pool[4133231]=new Object(); // elapsed 66.205s
# Unexpected InvocationTargetException: java.lang.Error: slow memory allocation
# Test failed.
However, JDK 1.3H classic VM quickly throws OutOfMemoryError when free memory became
near to be totally exhausted. (Indeed, HotSpot utilizes much more memory.)
>>>> D:\jdk1.3H\bin\java -classic except001
pool[1053880]=new Object(); // elapsed 1.282s
pool[1577980]=new Object(); // elapsed 1.702s
pool[1673958]=new Object(); // elapsed 1.112s
pool[1674703]=new Object(); // elapsed 1.122s
pool[1674709]=new Object(); // elapsed 1.111s
pool[1674710]=new Object(); // elapsed 1.122s
pool[1674711]=new Object(); // elapsed 2.223s
pool[1674712]=new Object(); // elapsed 2.233s
pool[1674713]=new Object(); // elapsed 2.234s
OutOfMemoryError thrown as expected.
Test passed.
I believe, that Java VM has to throw OutOfMemoryError rather than bring application
into hangup. So, this is a performance bug in HotSpot 1.3 Client VM beta-H.
HotSpot releases 1.0-fcs (both Sparc, and Win32) also suffer this problem; and
HotSpot 2.0-devA seems to suffer it too - it crashes after 4 minutes of execution
due to another known bug:
#4239828 (P1/S4) 1.3c1: VM crashes when heap is exhausted
I have executed the testing program on the following computers:
- Pentium-II, 350MHz, 128Mb RAM, Windows NT 4.0 Workstation, IE 4.01 active desktop
- Sparc Ultra-1, 200MHz, 128Mb RAM, Solaris 2.7, CDE
Following is the testing program source:
/* @(#)except001.java 1.1 99/06/23
* Copyright 99/06/23 Sun Microsystems, Inc.
*/
import java.io.*;
import java.lang.reflect.*;
/**
* This checks if <code>OutOfMemoryError</code> exception is correctly
* enwrapped into <code>InvocationTargetException</code> when thrown inside
* a method invoked via reflection.
*
* <p>The test tries to occupy all of memory available in the heap by
* allocating lots of new <code>Object()</code> instances. Instances of the
* ``empty'' type <code>Object</code> are the smallest objects, so they
* apparently should occupy most fine-grained fragments in the heap.
* Thus, there apparently should not remain any free space to incarnate new
* <code>Throwable</code> instance, and VM possibly could crash while trying
* to throw new <code>OutOfMemoryError</code> and enwrap it into new
* <code>InvocationTargetException</code> instance.
*
* <p>By the way, the test checks time elapsed to allocate memory.
* Both classic VM and HotSpot seem to fall into poor performance of memory
* allocation when heap is almost over. E.g.: HotSpot 1.3-betaH may spend
* more than 1 minute to allocate next <code>Object</code> in this case
* (tested on Pentium-II, 350MHz, 128Mb RAM). So, the test is treated failed
* if more then 5 minutes is spent to allocate ``last bytes'' of the memory.
*
* @author Eugene I. Latkin
*/
public class except001 {
/**
* This field allows or supresses printing with <code>display()</code> method.
* @see #display(Object)
* @see #complain(Object)
* @see #out
*/
private static final boolean MODE_VERBOSE = true;
/**
* Print execution trace if <code>MODE_VERBOSE</code> is <code>true</code> (optional).
* @see #MODE_VERBOSE
* @see #complain(Object)
* @see #out
*/
private static void display (Object message) {
if (MODE_VERBOSE)
out.println(message.toString());
out.flush();
};
/**
* Print error <code>message</code>.
* @see #display(Object)
* @see #out
*/
private static void complain (Object message) {
out.println("# " + message);
out.flush();
};
/**
* The log-stream assigned at runtime by the method <code>run(args,out)</code>.
* @see #display(Object)
* @see #complain(Object)
* @see #run(String[],PrintStream)
*/
private static PrintStream out;
/**
* Try to allocate upto 2<sup>23</sup> instances of the type <code>Object</code>.
* Such instances are most fine-grained, and thus they should occupy even smallest
* fragments of free memory in the heap.
*
* <p>By the way, break the test, if JVM has spent more than 5 minutes to allocate
* latest portions of memory.
*/
public static void raiseOutOfMemory () {
// Repository for objects, which should be allocated:
Object pool[];
int index=0;
try {
pool = new Object [1<<23]; // ~8 millions
} catch (OutOfMemoryError oome) {
throw new Error("cannot initiate the test");
};
// Sum up time spent, when it was hard to JVM to allocate next object
// (i.e.: when JVM has spent more than 1 second to allocate new object):
double totalDelay = 0;
long timeMark = System.currentTimeMillis();
for (; index<pool.length; index++) {
//-------------------------
pool[index] = new Object();
long nextTimeMark = System.currentTimeMillis();
long elapsed = nextTimeMark - timeMark;
timeMark = nextTimeMark;
//----------------------
if (elapsed > 1000) {
double seconds = elapsed / 1000.0;
display("pool[" + index + "]=new Object(); // elapsed "+ seconds + "s");
totalDelay += seconds;
if (totalDelay > 300)
throw new Error("slow memory allocation");
};
};
// This method should not return normally:
throw new Error("test seems too weak");
};
/**
* Invoke the method <code>raiseOutOfMemory()</code> with reflection, and check
* if the exception it throws is just <code>OutOfMemoryError</code> enwrapped
* into <code>InvocationTargetException</code> instance.
*
* <p>Before the test begins, <code>this.out</code> filed is assigned to the
* parameter <code>out</code>. Parameter <code>args[]</code> is ignored.
*
* @see #raiseOutOfMemory()
*/
public static int run (String args[], PrintStream out) {
except001.out = out;
Class testClass = except001.class;
try {
Method testMethod = testClass.getMethod("raiseOutOfMemory", new Class [0]);
Object junk = testMethod.invoke(null, new Object [0]);
} catch (InvocationTargetException ite) {
Throwable targetException = ite.getTargetException();
if (targetException instanceof OutOfMemoryError) {
display("OutOfMemoryError thrown as expected.");
display("Test passed.");
return 0;
};
complain("Unexpected InvocationTargetException: " + targetException);
complain("Test failed.");
return 2;
} catch (Exception exception) {
complain("Unexpected exception: " + exception);
complain("Test failed.");
return 2;
};
//
complain("The test has finished unexpectedly.");
complain("Test failed.");
return 2;
};
/**
* Re-call to <code>run(args,out)</code>, and return JCK-like exit status.
* (The stream <code>out</code> is assigned to <code>System.out</code> here.)
* @see #run(String[],PrintStream)
*/
public static void main (String args[]) {
int exitCode = run(args,System.out);
System.exit(exitCode + 95);
// JCK-like exit status.
};
}
======================================================================
Name: dkC59003 Date: 07/13/99
Unfortunately, the bug seems not totally fixed yet.
Though the problem no longer arises on PC having 128Mb of memory,
memory allocation still happens slow on PC having 64Mb of memory
installed. See the execution trace of the program "except001"
(the program ran under HotSpot 1.0.1-beta-C on Pentium 166MHz,
64Mb RAM, Windows NT 4.0 Workstation + Service Pack 3):
>>>> java except001
pool[589824]=new Object(); // elapsed 1.913s
pool[589825]=new Object(); // elapsed 2.213s
pool[3735249]=new Object(); // elapsed 234.968s
pool[3735250]=new Object(); // elapsed 71.353s
# Unexpected InvocationTargetException: java.lang.Error: slow memory allocation
# Test failed.
The "System Requirements" section of README for the HotSpot 1.0 reads:
"You should have a PC with at least 48 megabytes of RAM, running Windows NT 4.0.
Service Pack 3 is recommended."
The computer I used to verify the bug satisfies those "Sytem Requirements".
So, this is the HotSpot bug to slow down memory performance in this case.
======================================================================
- relates to
-
JDK-4239828 1.3c1: VM crashes when heap is exhausted
-
- Closed
-
-
JDK-4238555 1.1: InfiniteList does not throw OutOfMemoryError and it should
-
- Closed
-