Apache POI: сборка мусора не освобождает память [Java] - PullRequest
0 голосов
/ 14 декабря 2018

Привет всем!

В настоящее время я работаю над инструментом, который автоматически считывает файлы Excel и реструктурирует информацию в соответствии с заданным набором правил, используя Apache POI.Пока что проект идет отлично, но у меня есть одна проблема, которую я не могу решить:

- После закрытия рабочей книги выделенная для нее память не собирается сборщиком мусора.

Я разбил проблему на крошечный фрагмент кода, который повторяет проблему.Я собираюсь опустить блоки try / catch для удобства чтения:

//the declaration and creation of the objects is seperated due to ommitted try/catch blocks
Workbook wb = null;
FileInputStream fs = null;

//opening filestream and workbook
fs = new FileInputStream("C:/Users/XXX/somefile.xlsm");
wb = WorkbookFactory.create(fs);

//closing them again, making them available for garbage collection
fs.close();
wb.close();

//added to make sure that the reference to the workbook/filestream is null
fs = null;
wb = null;

//added to manually trigger gc in hope that this will fix it
Runtime.getRuntime().gc();

//wait forever for me to check the RAM usage
while(true){Thread.sleep(1000)};

Как только POI используется для открытия книги, создается впечатление, что он создает некоторый буфер, который заполняет максимальный объем памяти.определяется аргументом Xmx.Память не освобождается, когда я закрываю книгу.Я также попробовал версию без использования фабрики, чтобы проверить, могут ли быть потеряны ссылки через этот модуль, но не повезло ...

Может кто-нибудь дать мне подсказку о том, почему память неосвобожден / сборщик мусора?

Кстати, я использую Apache POI 3.17, но я также тестировал 4.0 (но не недавно выпущенный 4.0.1, tbh ... да, я хаки мошенничество ^^)

Большое спасибо заранее!

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Привет еще раз,

Я понял это: Java просто ленилась в сокращении выделения кучи.Поскольку для программного обеспечения требуется очень много памяти в течение очень короткого промежутка времени, мне удалось приручить поведение, используя следующие аргументы JVM:

-Xms32m
-Xmx1g
-XX:+UnlockExperimentalVMOptions
-XX:+UseG1GC 
-XX:MaxHeapFreeRatio=15 
-XX:MinHeapFreeRatio=5

Теперь память возвращается после завершения операции.

Вот ресурсы, которые я использовал, чтобы выяснить это:

Спасибо всем, кто внес свой вклад.Ура!

0 голосов
/ 14 декабря 2018

Из документации forn Runtime.gc ():

Запускает сборщик мусора.Вызов этого метода предполагает , что виртуальная машина Java затрачивает усилия на утилизацию неиспользуемых объектов, чтобы сделать доступной память, которую они занимают, для быстрого повторного использования.Когда управление возвращается из вызова метода, виртуальная машина сделала все возможное, чтобы утилизировать все отброшенные объекты.

Насколько я понимаю, JVM не нужно ничего перерабатывать, если она этого не хочет,даже если вы позвоните Runtime.gc().

...