2

My Android application has a native C++ layer and a Java layer. The Java layer accesses the native layer via JNI calls.

Can the C++ layer safely create C++ objects for its own internal use, and store them in C++ member variables? I'm talking about C++ objects that don't need to be accessed by Java code in any way, i.e. they are managed and deleted completely in the C++ layer. In other words, the same object (via a member variable) is accessed throughout multiple JNI calls, but only the C++ layer needs to access it.

I need confirmation in this matter, because I know that there are special JNI methods for handling objects (relevant terms: local reference, global reference, etc.). If I'm correct, these apply only for objects that are visible by (or created for) Java code as well.

Therefore, I suppose that native-only C++ objects can be created and deleted in the usual ways (such as new and delete), and Java doesn't need to know anything about them. No special interoperability considerations are necessary, as long as the objects and any references to them reside exclusively in the C++ layer. Is this correct? Can I define C++ classes and methods in this layer in the same way as if it was a usual C++ application without any JNI/Java interoperability? To be general, is it allowed to instantiate and store plain C++ objects, i.e. objects that are out of the authority of Dalvik/JVM?

Thomas Calc
  • 2,994
  • 3
  • 30
  • 56
  • 1
    Yes, of course. Look at this code, for example: http://stylishtoupee.blogspot.fr/2011/07/jni-example-with-class-instantiation-c.html – Alex F Jun 02 '14 at 13:50
  • Thanks. I suppose that your solution provides a "root" for the stateful C++ layer. I mean, we have to keep track about the "root" C++ object, and this is why you store its pointer in Java level. In "deeper" level, i.e. *inside* this C++ class, there can be further member variables (and additional C++ objects). References to those "further" objects don't need to be stored in Java level (we store them in the C++ class), but the "root" object must be, because this is how you can access the stateful C++ layer from Java code. – Thomas Calc Jun 02 '14 at 13:56
  • This sample just shows that there are no restrictions on creating C++ objects inside C++ library exposing API for Java. C++ instances may be passed to JNI client, or kept inside the library, making some internal work. – Alex F Jun 02 '14 at 16:31

1 Answers1

2

Indeed, the JNI methods for handling objects are for the Java objects.

You can create C/C++ objects in any way you can imagine (malloc/new), but: how will you preserve them across JNI calls? (If you need that, of course.) Two options:

  1. Convert the pointer into an integer and pass that integer to Java. (You will have to care about pointers stored in garbage-collected Java objects, you see, the integers do not imply freeing the native memory.)

  2. Have some C/C++ data structure with all the necessary references.

Thread-safety deserves separate consideration; if you try to store pointers in thread-local variables, you probably will never debug the code (you see, there's a life cycle mismatch).

Good results may be achieved with static global variables accessed from just one thread.

And keep in mind that Android may kill and restart your application's process, thus destroying everything stored in static variables, as well as your native data structures.

18446744073709551615
  • 16,368
  • 4
  • 94
  • 127
  • I was thinking about a combination of 1) and 2): the "root" C++ object is managed according to 1), and this C++ class can handle the rest of internal C++ stuff in itself (i.e. instantiate additional C++ objects and store them in member variables, this is how it would save the state across JNI calls). Does this sound correct? (Assuming that Android lifecycle/thread safety is handled properly.) – Thomas Calc Jun 02 '14 at 15:45
  • Yes, it does. Just remember that activities are killed and recreated each time the screen turns, and in some other less evident circumstances. I'd keep that pointer in the `Application` instance. And it's better to avoid pointers to native memory in objects that may be garbage-collected (just because it's easier to avoid it than to do it right). – 18446744073709551615 Jun 03 '14 at 05:13