Закрыть ANTLR4 CharStream (среда выполнения Java) - OutOfMemoryException - PullRequest
0 голосов
/ 14 января 2019

В настоящее время я пытаюсь проанализировать большой файл (~ 700 тыс. Строк) с помощью ANTLR, используя Java Runtime. Файл слишком большой, и синтаксический анализ приводит к исключению «Недостаточно памяти» (после назначения более 8 ГБ ОЗУ).

Поскольку мне не нужно разбирать все вместе, я смог разбить файл на несколько файлов, содержащих по несколько функций в каждом. Сейчас я запускаю несколько потоков, чтобы проанализировать каждый из полученных файлов.

Вот функция run () моего runnable для каждого потока:

public void run() {
    System.out.println("Starting to parse file " + this.filename);
    try {
        org.antlr.v4.runtime.CharStream stream = CharStreams.fromFileName(this.filename, Charset.defaultCharset());
        CPP14Lexer lexer = new CPP14Lexer(stream);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        CPP14Parser parser = new CPP14Parser(tokens);
        ParseTree tree = parser.translationunit();
        lexer = null;
        tokens = null;
        parser = null;
        tree = null;
    } catch (IOException e) {
        e.printStackTrace();
    }
    TheParser.current_temp_file.decrementAndGet();
    System.out.println("Finished parsing file " + this.filename);
}

Вот моя проблема : потоки работают хорошо. Я запускаю их 3 на 3 (используя статическое атомное целое число «TheParser.current_temp_file»), чтобы избежать проблемы с памятью. Однако потоки никогда не завершаются полностью. Таким образом, после выполнения они все еще живы, а память продолжает увеличиваться.

Я думаю, что проблема, вероятно, исходит от CharStream, который никогда не закрывается. Однако в классе org.antlrv4.runtime.CharStream такого метода нет.

Знаете ли вы, откуда возникла проблема и как я мог ее решить?

Спасибо!

1 Ответ

0 голосов
/ 15 января 2019

Действительно, close метод не существует, потому что CharStream - это общий интерфейс, а CharStreams, который создает экземпляры CharStream, позволяет создавать множество различных реализаций из многих источников. Для некоторых из них (например, CharStreams.fromString()) закрывать вообще нечего, а для других вы должны непосредственно закрывать основной поток.

Исходный код выглядит так, как будто файл считывается в память и затем закрывается в CharStreams даже до того, как вы овладеете экземпляром CharStream.

Я рекомендую вам исследовать, а не гадать. Это все еще падает на память? Запустите ваше приложение с помощью -XX:+HeapDumpOnOutOfMemoryError и исследуйте полученный дамп памяти. Нити не выходят? Используйте профилировщик (например, VisualVM ), чтобы увидеть, где застревают потоки.

...