Problems with global instances of C++ Classes

157 views
Skip to first unread message

John Gaby

unread,
Oct 25, 2010, 8:41:44 PM10/25/10
to android-ndk
I seem to recall someone saying that there were problems with global
instances of C++ classes when using the NDK (but I couldn't find any
references to it when I searched). Does anyone know if this is an
issue. I have a global class which has been behaving is a very
strange manner, and I am wondering if I should allocate the class
rather than have it declared as a global instance.

Thanks.

Tim Mensch

unread,
Oct 25, 2010, 9:23:03 PM10/25/10
to andro...@googlegroups.com
The big issue with static/global instances is that they won't always be
reinitialized between runs of the program.

Even something as seemingly harmless as a static bool can mess up your
application: Say you have a static bool that tells you whether OpenGL
has been initialized. Well, it'll be wrong when the application is run a
second time, because you'll have a new OpenGL state to contend with.

Similarly for any static state that is trying to track any global
application state or Java-related state.

Tim

John Gaby

unread,
Oct 25, 2010, 10:10:46 PM10/25/10
to android-ndk
Is that because your process doesn't normally terminate even though
your activity has? I assume that means that your destructors will
probably never be called either, correct?

Thanks

Robert Green

unread,
Oct 26, 2010, 11:16:06 AM10/26/10
to android-ndk
I think it's only a problem if you don't play nice with the Android
life cycle.

Use Activity.onDestroy as an opportunity to reset your native context.

Tim Mensch

unread,
Oct 26, 2010, 1:39:28 PM10/26/10
to andro...@googlegroups.com
On 10/26/2010 9:16 AM, Robert Green wrote:
I think it's only a problem if you don't play nice with the Android
life cycle.

Use Activity.onDestroy as an opportunity to reset your native context.
That doesn't work. Activity.onDestroy() for the dying context is called AFTER Activity.onCreate() for the new context, at least under some circumstances. I had all kinds of trouble with the application not working on restart because I believed that Activity lifecycle document (which is only valid for Java apps). I ended up learning about the problem when reading a bit of Android source code, which had this comment:
            /*
             * When the android framework launches a second instance of
             * an activity, the new instance's onCreate() method may be
             * called before the first instance returns from onDestroy().
             *
             * This semaphore ensures that only one instance at a time
             * accesses EGL.
             */
This is in the GLSurfaceView.java implementation from Android 1.6; the comment seems to be removed from 2.0, so maybe this has been fixed for later Android builds? Or maybe the semaphore didn't work, as it was based on the Java context, which really should be distinct, if I understand things. It would be nice if this issue were documented elsewhere, but that's the only place I've seen it mentioned "officially." In any event, I can guarantee you that onDestroy() is called before onCreate() in the same process for my 1.6-targeted app. No idea whether this happens in 2.0 or later.

I actually do my destruction of the native context in onCreate() when I detect a new JVM; I still have the call to destroy the context in onDestroy(), but I also have a check there to verify that it's the old and not the new context that's requesting destruction.

Tim

Robert Green

unread,
Oct 27, 2010, 11:30:35 AM10/27/10
to android-ndk
Wow,

Sorry if my info was wrong. This is certainly worth noting. Do you
have a code sample for detecting a new jvm?

Thanks

Tim Mensch

unread,
Oct 27, 2010, 11:53:21 AM10/27/10
to andro...@googlegroups.com
On 10/27/2010 9:30 AM, Robert Green wrote:
Sorry if my info was wrong.  This is certainly worth noting.  Do you
have a code sample for detecting a new jvm?
Sure, here's what I do. As part of the Java start-up sequence, I create an object "QcEventDispatch". Because it's created in Java, a new one is created when the new app is spawned. I keep a NewGlobalRef() to my QcEventDispatch() in the JNI code, and when I get a shut-down request, I check it like this:
JNIEXPORT void JNICALL Java_com_recharge_quickcharge_QcEventDispatch_qcShutDown
  (JNIEnv * env, jobject obj)
{
    if (!env->IsSameObject(gCurrentEventDispatch,obj))
    {
        LOGI("Ignoring a shutdown from the old process");
        return;
    }
    qcDoShutdown();
}
When I get a "create" call (actually I wait for the screen to be created), I check to see if the application thinks it's already been initialized. If so, I call qcDoShutdown() right away before re-creating the app; when the actual onDestroy() is called later, it triggers my JNI qcShutDown() call above, which then is ignored because by that time gCurrentEventDispatch has been set with the new object.

And as I said, if you're targeting 2.0 or newer, this may or may not happen; I haven't checked. I can only tell you what happens when I'm linked to 1.6, which I am right now.

Tim
Reply all
Reply to author
Forward
0 new messages