Comparison between jME2 and jME3

There’s no real solution to this, except to create a “dispose” method on the NativeObject, which will remove all of its data (both direct memory and OpenGL memory), and mark that object as unusable.

Wich might be an acceptable solution for some use cases? Maybee we should add that method. Eg Large terraintextures like a lightmap uses quite some memory

1 Like

I would like to cleanup my mess manually as it is explained in my article in the subsection entitled “Reduction of memory consumption”. I would like to handle several kinds of resources (identifiers and direct NIO buffers) manually at the most appropriate time, for example when switching from a level to another one. A dispose method would be fine. I think this problem can hardly be solved with an automatic build-in solution. Thank you for the detailed explanations.

@Momoko_Fan said: It happens in NativeObjectManager.deleteUnused() which is called every frame by the Renderer, so the deletion happens on the OpenGL thread. The main issue with this approach, is that the Java GC will ignore small objects, even more so if the Java heap size is large.

I wouldn’t worry too much about that.
With the native objects gone, the Java objects formerly referencing them aren’t special anymore and can wait until it’s their normal turn to be collected.

@toolforger said: I wouldn't worry too much about that. With the native objects gone, the Java objects formerly referencing them aren't special anymore and can wait until it's their normal turn to be collected.

You got it backwards, this method will remove native stuff from gc’d objects. There is currently no mechanism to free objects except the gc, wich will often only see a few bytes instead of the 128mb image behind that object.

1 Like
@toolforger said: I wouldn't worry too much about that. With the native objects gone, the Java objects formerly referencing them aren't special anymore and can wait until it's their normal turn to be collected.

Isn’t the whole point behind their posts that the huge native objects are not gone until the gc collects the small java objects. Which, as they said, can take quite some time, even enough time to run out of direct memory…? So you should worry.

2 Likes

Oh… NativeObjectManager doesn’t free native memory, just GL ids?
Then maybe objects that use native memory should become NativeObjects and go through NativeObjectManager. That would certainly help people with timely deallocation needs.

It does free the native memory, but not when you want it free, but when the gc cleans up the java side of the antive object…

If native memory is cleaned up during GC, then that’s via finalize() .
Then NativeObjectManager does not free the memory by itself, it tells somebody else to do it. From your mention of GC, I infer that it’s done during finalize().

I also see that using finalize() is not recommended practice.
If that’s advice to go by (which I don’t know whether it is), it would be better if NativeMemoryManager did indeed free the memory and didn’t defer that to GC.

1 Like

Well now is the time you should actually open that class. As it is not using finalize. Also if you have a good suggestion on how to determine wich objects to free and wich to keep it would be a good idea.

There’s no point in freeing native buffers at that point also, since the GC is just as likely to collect jME3’s objects than it is to collect native buffers. The only solution to this problem is what I mentioned in my post above.

1 Like

Ah, now that I’m sitting at my JME machine, I can fully follow the logic and see what’s actually happening.
I’ve been thinking that finalize() is the only way to get notified of the GC collecting garbage. I didn’t know that ReferenceQueue is an alternative approach, so telling me that stuff is getting deleted after GC didn’t make any sense to me; now it does.

Doesn’t NativeObject#deleteObject already do what the dispose proposal by @Momoko_Fan above does?

nearly, it does not have a flag if the object was already deleted.
Eg create boject
Manually kill it
Gc kill it -> Undefined behaviour since its illegal to delete already deleted objects

So basically adding a boolean and making that method public would solve that problem mostly?
(and adding everywhere where a native object is being used an assertion to prevent invalid objects to be activly used)

@Momoko_Fan
Did I get this right?
If so (and if you agree) I would volunteer to change this and then submit the patch.

I hope you’re aware of this.

There is no risk of crash when calling a cleaner several times on the same direct NIO buffer as you can see here.

How about adding a deleteObject routine to NativeObjectManager that takes care of removing the NativeObject from the list?

@toolforger said: How about adding a deleteObject routine to NativeObjectManager that takes care of removing the NativeObject from the list?

Yes, that could work

@gouessej said: I hope you're aware of this.

There is no risk of crash when calling a cleaner several times on the same direct NIO buffer as you can see here.


We don’t know how the buffer delete method is implemented in the Java VM, and nothing in the spec dictates that it should prevent double free. I’ve tested on JDK7 and encountered a native crash in that situation. In fact you can see it for yourself by running TestUseAfterFree on your machine.

@toolforger said: How about adding a deleteObject routine to NativeObjectManager that takes care of removing the NativeObject from the list?
It still won't prevent double delete when done by user. NativeObjectManager only tracks removals from GL, not native buffers/memory, so its actually cleared when the GL context is reset. Native buffers have longer lifetime than a GL object.
@Empire Phoenix said: @Momoko_Fan Did I get this right? If so (and if you agree) I would volunteer to change this and then submit the patch.
I've already did all the changes for it locally, I am still contemplating if it should be available or not.
1 Like

I was talking about a new NativeObjectManager.deleteObject.
It could be a noop if the object being deleted is not in the list of managed objects. (Possibly after emitting a warning at TRACE level.)

@toolforger said: I was talking about a new NativeObjectManager.deleteObject. It could be a noop if the object being deleted is not in the list of managed objects. (Possibly after emitting a warning at TRACE level.)

What would call it, though?

Any code that wants to make sure that stuff gets deleted regardless of when the GC kicks in.

1 Like

I’ve already did all the changes for it locally, I am still contemplating if it should be available or not.

Yes, dont limit the engine here. After all that method will onyl be found by those knowing why they need it anyway.