|
Description
|
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode)
java version "1.5.0_08"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_08-b03)
Java HotSpot(TM) Client VM (build 1.5.0_08-b03, mixed mode, sharing)
java version "1.6.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-beta2-b72)
Java HotSpot(TM) Client VM (build 1.6.0-beta2-b72, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows XP SP2
EXTRA RELEVANT SYSTEM CONFIGURATION :
2GB RAM
A DESCRIPTION OF THE PROBLEM :
Attempting to read a large file in one chunck with FileInputStream.read() with TOO large heap space causes OutOfMemory exception. According to spec, AFIK, even if the read() runs out of space it should just return with as much data as it can, not throw an exception. And in any case there was plenty of memory available, and further more with smaller heap the code runs ok!
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached code with heap space (-Xmx) 1300M and 1400M. With 1300M it runs ok, with 1400M it throws an exception. The "bigfile" in my test case had a length of 251 503 002 bytes. I can provide the file, but it should not make difference as the programs just tries to read all the bytes.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Either the FileInputStream.read() should have read the whole file (as there was 1400 MB of memory available and the file size was 'only' 250MB) or it should have read some smaller part of the file and returned the number of bytes read. It should not have thrown an exception.
ACTUAL -
With TOO large heap size the code throws OutOfMemory exception.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
C:\tests>"C:\Program Files\Java\jre1.6.0\bin\java.exe" -Xmx1400m -classpath . r3
d
size: 251503002
buf ok
Exception in thread "main" java.lang.OutOfMemoryError
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(Unknown Source)
at r3d.main(r3d.java:19)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.io.*;
public class r3d {
public static void main(String[] args) {
try {
int size = 501*501*501*2;
FileInputStream fis = new FileInputStream("bigfile"); // Any file with size >= 501*501*501*2
System.out.println("size: " + size);
byte buf[] = new byte[size];
System.out.println("buf ok");
int bytesRead = fis.read(buf, 0,size);
System.out.println("Bytes read " + bytesRead);
}
catch (Exception e) {
e.printStackTrace();
System.out.println(e);
System.out.println();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Attempting to read the file in multiple smaller chunks seem to work,.
Posted Date : 2006-10-05 09:11:13.0
|
|
Comments
|
Submitted On 06-DEC-2006
sebastiano.vigna
Same problem on Linux with
java version "1.5.0_09"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b01)
Java HotSpot(TM) Server VM (build 1.5.0_09-b01, mixed mode)
We used from -Xmx2000 to -Xmx2600M, but a read() into a 1.1GB array was always giving out-of-memory errors. Breaking the read() in 128KiB did work.
Submitted On 26-DEC-2006
hlavac
Happens to me too on Windows XP x64 with 32bit JVM.
Some more observations:
- Only happens on 32bit JVM with very large amounts of memory
- Problem happens in native method
- Both FileInputStream.read(byte[],int,int) and RandomAccessFile.read(byte[],int,int) are affected (same implementation?)
- The more memory you give to JVM, the smaller piece of data you can read on single read() without getting a mysterious OutOfMemoryError.
I have tested that on my system, with both JDK 1.5 and 1.6:
- with -Xms824m -Xmx824m you can still read up to 797,467,108 bytes long array in one read() call, which is the largest byte[] array you could get
- with -Xms825m -Xmx825m read of 799433188 bytes array throws OutOfMemoryError even though machine has 3GB physical RAM
- I was unable to set memory on Windows to more than -Xms1594m -Xmx1594m having 3GB of physical memory, anything more fails to start the JVM (2GB limitation?), and with this much memory you can read max 143,982,560 bytes without getting OutOfMemoryError.
Looks to me more like address space exhaustion than memory exhaustion???
Anyway it sucks when you want to process very large data.
Submitted On 26-DEC-2006
hlavac
Here, test case to play with:
[code]
package largefilereadbug;
import java.io.*;
public class Main {
public static final void main(String[] args) throws Throwable {
File f = File.createTempFile("biggie",".big").getCanonicalFile();
f.deleteOnExit();
RandomAccessFile raf = new RandomAccessFile(f,"rw");
try {
System.out.println("JVM: "+System.getProperty("java.vm.version"));
System.out.println("Max mem: "+Runtime.getRuntime().maxMemory());
System.out.println("Current mem: "+Runtime.getRuntime().totalMemory());
System.out.println("Finding size of largest allocatable array...");
int biggie = findMaximumByteArraySize();
System.out.println("Maximum allocatable: byte["+biggie+"]");
raf.setLength(biggie);
try {
byte[] data = new byte[biggie];
System.out.println("Got array, trying to read into it");
try {
raf.read(data);
} catch (OutOfMemoryError x) {
System.out.println("WTF!? got OutOfMemoryError from within read()!");
throw x;
}
System.out.println("SUCCESS!!! Everything works as it should.");
} catch (OutOfMemoryError e) {
System.out.println("This didnt work ;(");
throw e;
}
} finally {
raf.close();
f.delete();
}
}
static final int findMaximumByteArraySize() {
if (allocates(0x7fffffff)) return 0x7fffffff;
int max = 0x7fffffff; // upper bound
int min = 0; // lower bound
while (min<max) {
int half = (max-min)/2+min;
if (allocates(half)) {
// yes, go up with the lower bound
min = half+1;
} else {
// no, go down with upper bound
max = half-1;
}
}
return min;
}
static final boolean allocates(int size) {
byte[] test = null;
try {
test = new byte[size];
test = null;
System.gc();
return true;
} catch (OutOfMemoryError e) {
}
return false;
}
}
[/code]
Submitted On 13-MAR-2009
MichaelMcCandless
This is a nasty bug! It's affecting users of Lucene:
http://lucene.markmail.org/message/zpz6n5z3dx3gm2xi
Is it known whether this also affects 64 bit JREs?
Submitted On 21-MAR-2009
SanneGrinovero
Using Java HotSpot(TM) 64-Bit Server VM (build 14.0-b11, mixed mode)
on 64 bit linux (fedora 10) I don't have problems;
I've succesfully run the testcase submitted by hlavac with several configurations from 32m to 3GB.
So I think linux 64bit is not affected?
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|