Ошибка пространства кучи Java при чтении файла в байтовом массиве - PullRequest
1 голос
/ 28 декабря 2011

Я получаю Java из ошибки кучи при использовании следующего кода. Может кто-нибудь сказать мне, что я здесь делаю не так?

При отладке вижу, что значение длины равно 709582875

In main function 

File file = new File(fileLocation+fileName);
if(file.exists()){
s3Client.upload(bucketName,fileName,getBytesFromFile(file));
}


// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);

// Get the size of the file
long length = file.length();

// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
log.debug("file is too large"+length);
System.out.println("file is too large"+length);
}

if (length < Integer.MIN_VALUE || length > Integer.MAX_VALUE) {
throw new IOException
(length + " cannot be cast to int without changing its value.");
}

// return "test".getBytes();
// Create the byte array to hold the data

try{
byte[] bytes = new byte[(int)length];
}
catch(OutOfMemoryError e){ System.out.println(e.getStackTrace().toString());}

// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}

// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}

// Close the input stream and return bytes
is.close();
return bytes;
}

Ответы [ 6 ]

2 голосов
/ 28 декабря 2011

Вы используете 709582875 байт (около 677 МБ) в момент выделения байтового массива в блоке try. Это довольно много по обычным стандартам персональных компьютеров и потребляет большую часть (если не всю) памяти JVM, запущенной с настройками по умолчанию.

Некоторую информацию о настройках памяти JVM по умолчанию можно найти здесь

2 голосов
/ 28 декабря 2011

Проблема заключается в том, что массив байтов, который вы выделяете, слишком велик, и он занимает пространство кучи.

Вы можете попробовать запустить вашу программу с опциями -Xms и -Xmx, чтобы указать min и max heapпространство, которое использует виртуальная машина Java для запуска вашей программы.

Но я предлагаю вам не читать весь файл в байтовый массив для его обработки.Вы можете прочитать его часть в небольшой байтовый массив, обработать его и перейти к следующей части.Этот способ занимает меньше места в куче.

1 голос
/ 28 декабря 2011

Не создавайте такой огромный массив байтов [] .Ваша куча может выйти из памяти.Это плохая идея создать массив байтов [] длины файла для такого большого файла. создание небольшого байтового массива и чтение файла в чанке по частям

1 голос
/ 28 декабря 2011

Попробуйте увеличить размер кучи, выделенной виртуальной машиной Java (JVM), что-то вроде:

java -Xms<initial heap size> -Xmx<maximum heap size>

Например:
java -Xms64m -Xmx256m HelloWorld

0 голосов
/ 28 декабря 2011

Есть ли какая-то конкретная причина, по которой вам нужно читать весь файл сразу как байт []?Можете ли вы использовать вместо этого отображенный в памяти ByteBuffer, так как он использует очень маленькую кучу независимо от размера файла.

0 голосов
/ 28 декабря 2011

нужна настройка jvm java -Xms256m -Xmx1024m

...