FileInputStream Утечка памяти в цикле чтения файла - PullRequest
3 голосов
/ 02 февраля 2011

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

package it.datapump.main;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;


public class TifReader {

public static void main (final String[] a){

    for (int i = 0; i < 100000; i++) {
        try {
            getBytesFromFile(new File("test.tif"));
            Thread.sleep(1000);
            System.gc() ;
        } catch (Exception ex) {
        }
    }
}

public static byte[] getBytesFromFile(File file) throws IOException {
    InputStream is = new FileInputStream(file);
    long length = file.length();

    byte[] bytes = new byte[(int)length];
    int offset = 0;
    int numRead = 0;
    while (offset < bytes.length
           && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
        offset += numRead;
    }
    is.close();

    // Do something with the read bytes
    //

    if (offset < bytes.length) {
        throw new IOException("Could not completely read file "+file.getName());
    }
    return bytes;
}
}

Теперь ... мы просто не можем увидеть вескую причину, по которой этот код потребляет память до самого верха и в концевыдает исключение OutOfMemoryError.
Есть идеи?

Что-то еще
Проблема возникает при использовании Java Development Kit Version 6 Update 23, но не в JRE 1.7

Ответы [ 4 ]

2 голосов
/ 02 февраля 2011

Этот код должен работать нормально (за исключением того факта, что создание нового файла столько раз не имеет смысла).

Я запускал ваш код в цикле 10 миллионов раз, и он не выдал OOME. Фактически, использование памяти было постоянным, около 50 МБ.

Итак, я думаю, что проблема должна быть в другом.

1 голос
/ 02 февраля 2011

Я бы запустил ваш код на профилировщике, подобном Visual VM , и посмотрел бы, где используется память.

Я предполагаю, что выполнение команды "что-то с байтовым кодом" может вызвать проблемы. Также не рекомендуется вызывать System.gc (), поскольку сборщик garabge должен знать сам, когда он должен быть вызван.

0 голосов
/ 03 февраля 2011


Потеряв время и затрачивая на это внимание, мы обнаружили, что проблема связана с тем, как пакет был установлен на целевой машине.
Наш программист создал исполняемый jar, содержащий все необходимые jar, вместо использованияте, которые уже установлены на целевой машине.Итак ... «что-то» было другим, даже если мы на самом деле не знаем что, и процедура теперь больше не теряет память.

Кто-нибудь может мне это объяснить?(Я должен сказать, что я разработчик C / C ++, а не Java, и я пишу о работе моего коллеги).

0 голосов
/ 02 февраля 2011

Поскольку вы эффективно выбрасываете байты, считанные из файла на каждой итерации, я не вижу причин для получения OOME, если только размер файла не превышает Xmx по умолчанию для вашего процесса JVM (просто мыслительный процесспоскольку я знаю, что файлы TIF печально известны своим огромным размером по сравнению с другими форматами изображений).

Кроме того, распечатайте номер итерации.Вы всегда получаете OOME с одинаковым количеством итераций?Или вы «используете» байты, прочитанные из файлового потока?

...