Утечка памяти в строке Java - PullRequest
1 голос
/ 21 мая 2011

Я задавал подобный вопрос раньше: Утечка памяти в строке Java

Но я не был уверен, что спросить:

Вот еще один фрагмент кода, который я написал:

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;


public class TestString {
    public static int  readLineXX(BufferedReader br) throws Exception {
            String s = br.readLine();
            if ( s == null ) return 0;
            return 1;
    }
    public static void main(String args[]) {
        while (true) {
        try {
            FileInputStream fstream = new FileInputStream("bigfile.txt");
            DataInputStream in = new DataInputStream(fstream);
            BufferedReader  br = new BufferedReader(new InputStreamReader(in));
            while ( readLineXX (br)!= 0) {
                //System.out.print(".");
            }
            br.close();
            in.close();
            fstream.close();
        } catch (Exception e) {
        }       
    }
    }
}

Поскольку строка в Java неизменна, String s будет собирать мусор. Я долго запускал этот код, используя опции -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails, он работает нормально.

Это небольшой фрагмент моего основного приложения, в котором, как мне кажется, есть утечка и причина OOM. bigfile.txt около 1GB.

Ответы [ 4 ]

4 голосов
/ 21 мая 2011

Да, s будет собирать мусор. Быть неизменным не мешает сборке мусора, а только предотвращает его изменение.

Обратите внимание, что br.readlLine() потенциально будет использовать большой объем памяти, если строка очень большая. Например, если ваш текстовый файл занимает 1 ГБ без каких-либо разрывов строк, то br.readLine() вполне может потреблять 2 ГБ, 1 ГБ для считываемых данных, а затем 1 ГБ для созданной строки.

1 голос
/ 21 мая 2011

вместо

        FileInputStream fstream = new FileInputStream("bigfile.txt");
        DataInputStream in = new DataInputStream(fstream);
        BufferedReader  br = new BufferedReader(new InputStreamReader(in));

вы можете использовать

        BufferedReader  br = new BufferedReader(new FileReader("bigfile.txt"));

Единственный способ вызвать OOME - это иметь очень длинные строки и ограниченную память.Вы используете опции -Xmx?Почему вы используете DataInputStream - это двоичные или текстовые данные?

1 голос
/ 21 мая 2011

Символы String в вашем коде не могут вызвать утечку памяти, поскольку после возврата из readLineXX на них нигде не ссылаются, поэтому все они будут собирать мусор. Мои подозреваемые - скорее потоки, которые вы используете. Я могу себе представить, что для входного файла объемом 1 ГБ входные потоки могут быть довольно большими.

Один из способов проверить это - разрезать ваш входной файл на 2 или более частей и прочитать каждую из них по очереди. Если виновниками являются потоки, чтение нескольких меньших входных файлов по одному не должно вызывать утечку памяти.

0 голосов
/ 21 мая 2011

В коде нет явных утечек памяти.

Дамп кучи с аргументом -XX:+HeapDumpOnOutOfMemoryError JVM и анализ результатов . (Я предполагаю, что Java 6 Hotspot JVM; если вы используете другой, вероятно, будут аналогичные варианты.)

DataInputStream является избыточным; потоки должны быть закрыты в окончательных блоках; но я не понимаю, как такие вещи могут повлиять на ошибки, о которых вы сообщаете.

...