sapiensl
sapiensl

Reputation: 81

Apache POI: garbage collection does not free memory [Java]

Hi everyone!

I am currently working on a tool that automatically reads excel files and restructures information according to a given set of rules using Apache POI. The project is going great so far, but I have one problem that I am not able to resolve:

- After closing a workbook, the memory allocated for it is not garbage collected.

I have broken down the problem into a tiny piece of code that replicates the issue. I am going to omit try/catch blocks for the sake of readability:

//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)};

As soon as POI is used to open a workbook, it seems to create some kind of buffer that fills the maximum amount of memory specified by the Xmx argument. The memory is not freed when I close the workbook. I also tried a version without the use of the factory to check if there might be lost references through that module, but no luck...

Can someone give me a hint on why the memory is not deallocated/garbage collected?

By the way, I am using Apache POI 3.17, but I also tested 4.0 (but not the recently released 4.0.1, tbh... yes, I am a hack and a fraud ^^)

Thank you very much in advance!

Upvotes: 4

Views: 5050

Answers (2)

sapiensl
sapiensl

Reputation: 81

Hi again,

I figured it out: Java was just lazy in reducing the heap allocation. Since the software only requires a lot of memory for a very short amount of time, I managed to tame the behaviour using the following JVM arguments:

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

Now, the memory is returned after the operation is finished.

Here are the resources I used to figure it out:

Thank you to all who contributed. Cheers!

Upvotes: 4

Amongalen
Amongalen

Reputation: 3131

From documentation forn Runtime.gc():

Runs the garbage collector. Calling this method suggests that the Java virtual machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the virtual machine has made its best effort to recycle all discarded objects.

From my understanding JVM doesn't have to recycle anything if it doesn't want to, even if you call Runtime.gc().

Upvotes: 1

Related Questions