Are NewWeakGlobalRef()/DeleteWeakGlobalRef() already implemented?

829 views
Skip to first unread message

tueda

unread,
Apr 21, 2011, 8:06:26 PM4/21/11
to android-ndk
Hi,

Are NewWeakGlobalRef()/DeleteWeakGlobalRef() already implemented?
I expect the answer is NO.
When I use returned jweak value, It always crash.

And I found this e-mail (http://groups.google.com/group/android-
developers/browse_thread/thread/c8c84265a97cd2f4).
They were not implemented yet, "but you should see it sooner rather
than later".

alan

unread,
Apr 22, 2011, 12:53:45 PM4/22/11
to andro...@googlegroups.com
its in 2.3

fadden

unread,
Apr 22, 2011, 2:18:03 PM4/22/11
to android-ndk
On Apr 21, 5:06 pm, tueda <tu...@wolf.dog.cx> wrote:
> Are NewWeakGlobalRef()/DeleteWeakGlobalRef() already implemented?
> I expect the answer is NO.

They were introduced in Android 2.2 ("froyo").

tueda

unread,
Apr 24, 2011, 2:08:27 AM4/24/11
to android-ndk
Thank you for your replies.
I tried again NewWeakGlobalRef() in Android 2.2, 2.3.1, 2.3.3 and 3.0
in the Android emulator, All crashed.
I'm sure that Weak Global Reference of Android is still buggy and
doesn't work yet.

tested code:
/*
* Class: org_karlsland_MainActivity
* Method: call_jni
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_karlsland_MainActivity_call_1jni
(JNIEnv* env, jclass clazz)
{
jfieldID witches_field = env->GetStaticFieldID (clazz,
"witches", "Ljava/util/List;");
jobject witches_obj = env->GetStaticObjectField (clazz,
witches_field);
jclass list_class = env->GetObjectClass (witches_obj);
jmethodID list_add = env->GetMethodID (list_class,
"add", "(Ljava/lang/Object;)Z");

jobject g_witches_obj = env->NewWeakGlobalRef (witches_obj);

jclass witch_class = env->FindClass ("org/karlsland/Witch");
jmethodID witch_init = env->GetMethodID (witch_class, "<init>",
"(I)V");

for (int i = 0; i < 4; i++) {
jobject witch_obj = env->NewObject (witch_class, witch_init,
i);
env->CallBooleanMethod (g_witches_obj, list_add, witch_obj);
env->DeleteLocalRef (witch_obj);
}
}

Igor R

unread,
Apr 24, 2011, 5:38:12 AM4/24/11
to andro...@googlegroups.com
> I tried again NewWeakGlobalRef() in Android 2.2, 2.3.1, 2.3.3 and 3.0
> in the Android emulator, All crashed.
> I'm sure that Weak Global Reference of Android is still buggy and
> doesn't work yet.

FWIW, I use NewWeakGlobalRef without any problem.
Check your logcat output to see where it crashes and why,

tueda

unread,
Apr 24, 2011, 10:09:12 PM4/24/11
to android-ndk
As far as I know, Everything point to a buggy implementation of
NewWeakGlobalRef() on Android (all version).
Let's consider this simplest code.
It calls java.lang.String.length() from C++.

/*
* Class: org_karlsland_MainActivity
* Method: call_native_code
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_org_karlsland_MainActivity_call_1native_1code
(JNIEnv* env, jclass clazz)
{
__android_log_print (ANDROID_LOG_INFO, "NativeCode", "NativeCode
is called.");

jclass string_class = env->FindClass ("java/lang/String");
jobject string_obj = env->NewStringUTF ("Hello World");
jmethodID string_length = env->GetMethodID (string_class,
"length", "()I");
jweak global_string_obj = env->NewWeakGlobalRef(string_obj);

__android_log_print (ANDROID_LOG_INFO, "NativeCode",
"string_class = %p.", string_class);
__android_log_print (ANDROID_LOG_INFO, "NativeCode",
"string_obj = %p.", string_obj);
__android_log_print (ANDROID_LOG_INFO, "NativeCode",
"string_length = %p.", string_length);
__android_log_print (ANDROID_LOG_INFO, "NativeCode",
"global_string_obj = %p.", global_string_obj);

int len;

len = env->CallIntMethod (string_obj, string_length);
__android_log_print (ANDROID_LOG_INFO, "NativeCode",
"String.length = %d.", len);

len = env->CallIntMethod (global_string_obj, string_length);
__android_log_print (ANDROID_LOG_INFO, "NativeCode",
"String.length = %d.", len);
}

And this works fine at least in Ubuntu 10.10.
But in Android, this always crash with SIGSEGV when env-
>CallIntMethod() is invoked (which uses jweak value).
And fault address(0xdae1b6bf) indicates just jweak value returned by
env->NewWeakGlobalRef().

04-25 01:36:31.374: INFO/NativeCode(5406): NativeCode is called.
04-25 01:36:31.374: INFO/NativeCode(5406): string_class =
0x4000d1c8.
04-25 01:36:31.385: INFO/NativeCode(5406): string_obj =
0x44ee48e0.
04-25 01:36:31.385: INFO/NativeCode(5406): string_length =
0x4188786c.
04-25 01:36:31.385: INFO/NativeCode(5406): global_string_obj =
0xdae1b6bf.
04-25 01:36:31.394: INFO/NativeCode(5406): String.length = 11.
04-25 01:36:31.514: INFO/DEBUG(31): *** *** *** *** *** *** *** ***
*** *** *** *** *** *** *** ***
04-25 01:36:31.514: INFO/DEBUG(31): Build fingerprint: 'generic/sdk/
generic/:2.2/FRF91/43546:eng/test-keys'
04-25 01:36:31.524: INFO/DEBUG(31): pid: 5406, tid: 5406 >>>
org.karlsland <<<
04-25 01:36:31.524: INFO/DEBUG(31): signal 11 (SIGSEGV), fault addr
dae1b6bf
04-25 01:36:31.544: INFO/DEBUG(31): r0 00000007 r1 4188786c r2
4188786c r3 bec06854
04-25 01:36:31.544: INFO/DEBUG(31): r4 dae1b6bf r5 0000ccb0 r6
4188786c r7 bec06854
04-25 01:36:31.564: INFO/DEBUG(31): r8 4000d1c8 r9 dae1b6bf 10
0000ce04 fp 4186bce0
04-25 01:36:31.564: INFO/DEBUG(31): ip 80888110 sp bec067d8 lr
80846dad pc 80840d8e cpsr 00000030


Say again, I'm sure that weak global reference on Android doesn't
work.
Do you have any idea?



fadden

unread,
Apr 25, 2011, 4:20:59 PM4/25/11
to android-ndk
On Apr 24, 7:09 pm, tueda <tu...@wolf.dog.cx> wrote:
>     jobject   string_obj        = env->NewStringUTF ("Hello World");
>     jweak     global_string_obj = env->NewWeakGlobalRef(string_obj);
[...]
>     len = env->CallIntMethod (global_string_obj, string_length);
>     __android_log_print (ANDROID_LOG_INFO, "NativeCode",
> "String.length = %d.", len);

Ah. The spec says:

"Since garbage collection may occur while native methods are running,
objects referred to by weak global references can be freed at any
time. While weak global references can be used where global references
are used, it is generally inappropriate to do so, as they may become
functionally equivalent to NULL without notice."

From jni-tips.html:

* "Weak global" references are implemented, but may only be passed to
NewLocalRef, NewGlobalRef, and DeleteWeakGlobalRef. (The spec strongly
encourages programmers to create hard references to weak globals
before doing anything with them, so this should not be at all
limiting.)


So, yes, Android does not have a complete implementation. The pointer
is XORed with 0x9e0fffff in an attempt to cause the VM to crash
reliably when weak globals are used in this way.

tueda

unread,
Apr 25, 2011, 10:37:36 PM4/25/11
to android-ndk

I see. It's great information.
I keep exactly same object-references in both Java and C++,
So there is no need to worry about direct use of weak global
references.
But anyway, I promote from weak global reference to local reference
before every use.
The problem is solved. Thank you for your help.

Jni-tips.html is very useful.
I hope android-ndk/docs contains it for ease of use.

Igor R

unread,
Apr 26, 2011, 5:38:07 AM4/26/11
to andro...@googlegroups.com
> Ah.  The spec says:
>
> "Since garbage collection may occur while native methods are running,
> objects referred to by weak global references can be freed at any
> time. While weak global references can be used where global references
> are used, it is generally inappropriate to do so, as they may become
> functionally equivalent to NULL without notice."
>
> From jni-tips.html:
>
> * "Weak global" references are implemented, but may only be passed to
> NewLocalRef, NewGlobalRef, and DeleteWeakGlobalRef.


That's interesting information...

In my code I pass a weak ref as a parameter (in a native thread context):
if (!env_->IsSameObject(myWeakRef_, NULL))
env_->CallVoidMethod(someObj_, method_, myWeakRef_);
And it always works as expected.
How do you explain this?

Reply all
Reply to author
Forward
0 new messages