Освобождение памяти Java в определенный момент времени - PullRequest
2 голосов
/ 25 марта 2010

Учитывая этот код, где мы загружаем много данных, записываем их в файл, а затем запускаем exe ..

void myMethod() {
    Map stuff = createMap(); //Consumes 250 MB memory
    File file = createFileInput(stuff); //Create input for exe
    runExectuable(file); //Run Windows exe
}

Каков наилучший способ освободить память, занятую stuff перед запуском exe? Нам это больше не нужно в памяти, так как мы сбросили данные в файл для ввода в exe ...

Является ли лучший способ просто установить stuff = null до runExecutable(file)?

Ответы [ 9 ]

4 голосов
/ 25 марта 2010

Наверное, лучший ответ: ничего не делать.

Компилятор Java довольно умен. Он может сказать, что stuff больше не нужен после createFileInput(stuff) и переписывает код, чтобы убедиться, что он GCable. Вы можете установить его на нуль, если хотите быть на 100% уверенным, но компилятор, возможно, уже сделал это для вас. И установка его в нуль не гарантирует, что это будет GC'd.

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

РЕДАКТИРОВАТЬ: обратите внимание, что компилятор может быть либо javac, либо JIT-компилятором. Оба прекрасно осведомлены о подобных вещах и проводят всевозможные оптимизации, которые вы не могли бы себе представить. Итог: напишите чистый код, затем профилируйте его и оттуда оптимизируйте.

EDIT2: Для тех, кто интересуется уловками, которые JVM играет с памятью, я настоятельно рекомендую этот блог (который достаточно хорошо объясняет эту проблему): http://jeremymanson.blogspot.com/2010/02/garbage-collection-softreferences.html

1 голос
/ 25 марта 2010

Если вас не устраивает то, что предложил @noah (ничего не делать), или код запускается в среде, в которой нет JIT или общих оптимизаций времени выполнения, гораздо более чистая альтернатива для установки на нуль и вызова System .gc () будет разбивать ваш код так, что.

void myMethod() {
    File file = prepareFile(); //Prepare file for window exe
    runExectuable(file); //Run Windows exe
}

private File prepareFile() {
    Map stuff = createMap(); //Consumes 250 MB memory
    return createFileInput(stuff); //Create input for exe
}

Это более чистый код, который позволит stuff иметь право на сбор, как только он выпадет из области видимости. Явное значение null и вызов gc () - это просто хаки.

0 голосов
/ 26 марта 2010

Моя первая мысль не об изменении объема ссылок или принудительной сборке мусора, но может ли быть уменьшена потребность в памяти?

Можно ли реорганизовать функциональность, чтобы можно было сгенерировать stuff во время записи в файл? Например, вы можете уменьшить createMap и creatFile до чего-то, что вычисляет часть карты

while (mapFiller.hasMore()) {
    Map map = mapFiller.getNextPartialMap();
    mapWriter.writePartialMap(map);
}

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

Также см .: JVM отправляет обратно память в ОС и Java VM - возвращается ли освобожденная память в ОС?

0 голосов
/ 25 марта 2010

@ jpalecek Как вы думаете, как именно System.gc () выполнит что-либо большее, чем любая другая сборка мусора, вызванная jvm при нехватке памяти ()? Автоматическая сборка мусора означает именно это.

0 голосов
/ 25 марта 2010

Поскольку материал Map объявляется локально внутри метода, он должен иметь право на сборку мусора после выхода из метода.

0 голосов
/ 25 марта 2010
void myMethod() {
    runExectuable(createFile()); //Run Windows exe
}

File createFile() {
    Map stuff = createMap(); //Consumes 250 MB memory
    return createFileInput(stuff); //Create input for exe
}
0 голосов
/ 25 марта 2010

Установка stuff на null, безусловно, необходима, но этого будет недостаточно без принудительного сбора мусора. Я полагаю, что функция runExecutable будет ждать до завершения выполнения, поэтому я запускаю System.gc() в другом потоке, чтобы во время ожидания происходил сбор мусора.

0 голосов
/ 25 марта 2010

Установка объекта карты на ноль - хорошая идея. Вы можете даже попытаться сделать System.gc () явно после установки нулевого значения map.

Но помните, что сборщик мусора будет работать только по собственному расписанию, и выполнение любого из них не гарантирует, что сборщик мусора будет работать в этот момент самостоятельно Но если для вашей карты установлено значение null, вы не получите OutOfMemory в обычных случаях, так как в худшем случае, когда jvm достигнет максимального размера кучи, он наверняка запустит сборщик мусора и, следовательно, освободит память.

0 голосов
/ 25 марта 2010

В качестве альтернативы:

 runExecutable(createFileInput(createMap()));

Будьте осторожны, чтобы метод createFileInput не держал ссылку на экземпляр Map!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...