How to lower the allocated objects in memory?

So I am working on a voxel game (because its a good place to start learning 3d) and I recently did the chunkloader, so now when you move around it creates new chunks where you are and “unloads” those where you arent. Eventually unloading will mean saving them to the disk then removing them from memory but at the moment it just means removing them from memory.
I have a queue chunks needed to be unloaded get put in and I remove one object from that queue once every 5 frames or so. Once the last object is removed from the queue I call System.gc(). This isn’t a great solution but what I found was if I didn’t do this then the removed chunks would never be removed from memory. Since I implemented this the live bytes in the memory profiler are no longer going up but the allocated objects will not go down. Is there a way to release this memory from the JVM?
Heres a graph from the profiler:
From this you can see the spikes when GC is called.

I have had trouble with getting the JVM to clean up memory in the past and I probably am doing something wrong, but the fact that the live bytes and objects have gone down so steeply leads me to believe I am removing all references from the objects correctly.

In this case would am object pool be effective? There is a limit to the number of chunks that are loaded at any given time so logically I think it would work, but I’m not sure if it would be worth the memory performance. Anyone got any ideas?

Edit: Heres a table that illustrates it well:
Although only 0.1% of my live objects are Vector3f’s there are 15 million allocated objects. The Block object contains only a boolean by the way, so thats ok to have many of it allocated.

They will be cleaned up at some point if you don’t keep any references to it. Do you get oom exceptions? If not everything is fine. You don’t need to empty the memory manually, this is java. It will use all the memory you assign it to and in the OS task manager the displayed “used” memory will never go down, that is normal and intended. As soon as java uses some system memory it also manages that memory and hence from the perspective of the OS that memory is “used”.

<cite>@normen said:</cite> They will be cleaned up at some point if you don't keep any references to it. Do you get oom exceptions? If not everything is fine. You don't need to empty the memory manually, this is java. It will use all the memory you assign it to and in the OS task manager the displayed "used" memory will never go down, that is normal and intended. As soon as java uses some system memory it also manages that memory and hence from the perspective of the OS that memory is "used".
No OOM exceptions but the further I travel in the world the higher memory goes. Eventually going up to 8gb at which point my pc runs out of ram and everything starts freezing, no crash though. Thats without calling gc, with calling GC it seems to top out at 2.5gb ram. Which still isn't good.
<cite>@maxyme said:</cite> So I am working on a voxel game (because its a good place to start learning 3d)

Actually, I’d argue that it is one of the single hardest places to start… but you are well underway now so that argument is moot. :slight_smile:

<cite>@maxyme said:</cite> I have a queue chunks needed to be unloaded get put in and I remove one object from that queue once every 5 frames or so. Once the last object is removed from the queue I call System.gc(). This isn't a great solution but what I found was if I didn't do this then the removed chunks would never be removed from memory. Since I implemented this the live bytes in the memory profiler are no longer going up but the allocated objects will not go down. Is there a way to release this memory from the JVM? Heres a graph from the profiler: From this you can see the spikes when GC is called.

I have had trouble with getting the JVM to clean up memory in the past and I probably am doing something wrong, but the fact that the live bytes and objects have gone down so steeply leads me to believe I am removing all references from the objects correctly.

In this case would am object pool be effective? There is a limit to the number of chunks that are loaded at any given time so logically I think it would work, but I’m not sure if it would be worth the memory performance. Anyone got any ideas?

Edit: Heres a table that illustrates it well:
Although only 0.1% of my live objects are Vector3f’s there are 15 million allocated objects. The Block object contains only a boolean by the way, so thats ok to have many of it allocated.

It sounds like maybe you’ve set your regular heap max very large.

Java won’t GC direct memory unless it runs normal GC to clean up its own memory. It won’t ever do this if the regular heap max is so large that regular heap allocation will never reach it. Best advice is to keep your main heap max only as big as is reasonable and set the direct memory max very large.

You can also specifically destroy your direct buffers when you are done with them using a method on BufferUtils. Make sure you only do this when you are really done with them or very bad things could happen (JVM crashes, blue screen of death, etc.).

You probably have the java heap too big in comparison to the direct heap.

This isn’t really related to the problem. but how were you able to list the allocated objects like that? It looks like that was done with Jconsole but I didn’t see any menu in jconsole that listed the classes out individually.

@icamefromspace said: This isn't really related to the problem. but how were you able to list the allocated objects like that? It looks like that was done with Jconsole but I didn't see any menu in jconsole that listed the classes out individually.
Use the profiler in the SDK

Thanks guys, I’ll fix the heap size.

<cite>@icamefromspace said:</cite> This isn't really related to the problem. but how were you able to list the allocated objects like that? It looks like that was done with Jconsole but I didn't see any menu in jconsole that listed the classes out individually.
This will help you set it up if you havent found it already https://wiki.jmonkeyengine.org/legacy/doku.php/sdk:debugging_profiling_testing