質問

I have an implementation of WallpaperService.Engine that uses JNI to create a C++ renderer:

Engine (Java) -> Renderer (C++)

If the renderer was Java code I could simply state

private Renderer renderer = new Renderer();

to make sure the renderer was created with my Engine and destroyed automatically when it's not needed any more. So what is the cleanest way to do this?

P.S.: I was thinking:

int rendererId = createNativeRenderer();
...
draw(rendererId); // call all native renderer methods specifying the object id
...
deleteNativeRenderer(rendererId); 

But it's not very elegant since it requires explicit deletion, which is easy to forget.

役に立ちましたか?

解決

Yes it's not very elegant, but it's by far the most reliable way. Java tries to be a hammer for every nail, so there is this thing called finalizer - an Object method called upon garbage collecting your instance. So it ideally does exactly what you need but practically better be avoided. If you read the related Javadoc carefully, you'll find out that:

  • Your precious renderer deleting code will be called not when you or your code thinks it's appropriate, but when the reference counting engine decides. And even worse, not at that specific point, but at any time later.
  • You can't know and you can't influence, which thread will call the finalizer. A double barrel shot in the foot if the code is related to UI operations (i understand that your code is).

Though, you can use finalizer for a safety check.

  1. wrap the renderer lifecycle (create/use/delete) in an object with public method for deleting
  2. upon explicit deleting, set an internal flag
  3. override finalize() and check the flag state there. If not marked as deleted, log nasty error
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top