Skip to content

Commit fa36abe

Browse files
committed
Fix FindClass() failing to find Dictionary on Android leading to crash
1 parent dda2614 commit fa36abe

File tree

5 files changed

+125
-48
lines changed

5 files changed

+125
-48
lines changed

platform/android/java_class_wrapper.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
123123
if (ref.is_valid()) {
124124
if (Object::cast_to<JavaObject>(ref.ptr())) {
125125
Ref<JavaObject> jo = ref;
126-
jclass c = env->FindClass(cn.utf8().get_data());
126+
jclass c = jni_find_class(env, cn.utf8().get_data());
127127
if (!c || !env->IsInstanceOf(jo->instance, c)) {
128128
arg_expected = Variant::OBJECT;
129129
} else {
@@ -223,7 +223,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
223223
if (cn.begins_with("[L") && cn.ends_with(";")) {
224224
cn = cn.substr(2, cn.length() - 3);
225225
}
226-
jclass c = env->FindClass(cn.utf8().get_data());
226+
jclass c = jni_find_class(env, cn.utf8().get_data());
227227
if (c) {
228228
for (int j = 0; j < arr.size(); j++) {
229229
Ref<JavaObject> jo = arr[j];
@@ -316,7 +316,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
316316
argv[i].d = *p_args[i];
317317
} break;
318318
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_BOOLEAN: {
319-
jclass bclass = env->FindClass("java/lang/Boolean");
319+
jclass bclass = jni_find_class(env, "java/lang/Boolean");
320320
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(Z)V");
321321
jvalue val;
322322
val.z = (bool)(*p_args[i]);
@@ -325,7 +325,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
325325
to_free.push_back(obj);
326326
} break;
327327
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_BYTE: {
328-
jclass bclass = env->FindClass("java/lang/Byte");
328+
jclass bclass = jni_find_class(env, "java/lang/Byte");
329329
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(B)V");
330330
jvalue val;
331331
val.b = (int)(*p_args[i]);
@@ -334,7 +334,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
334334
to_free.push_back(obj);
335335
} break;
336336
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_CHAR: {
337-
jclass bclass = env->FindClass("java/lang/Character");
337+
jclass bclass = jni_find_class(env, "java/lang/Character");
338338
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(C)V");
339339
jvalue val;
340340
val.c = (int)(*p_args[i]);
@@ -343,7 +343,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
343343
to_free.push_back(obj);
344344
} break;
345345
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_SHORT: {
346-
jclass bclass = env->FindClass("java/lang/Short");
346+
jclass bclass = jni_find_class(env, "java/lang/Short");
347347
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(S)V");
348348
jvalue val;
349349
val.s = (int)(*p_args[i]);
@@ -352,7 +352,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
352352
to_free.push_back(obj);
353353
} break;
354354
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_INT: {
355-
jclass bclass = env->FindClass("java/lang/Integer");
355+
jclass bclass = jni_find_class(env, "java/lang/Integer");
356356
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(I)V");
357357
jvalue val;
358358
val.i = (int)(*p_args[i]);
@@ -361,7 +361,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
361361
to_free.push_back(obj);
362362
} break;
363363
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_LONG: {
364-
jclass bclass = env->FindClass("java/lang/Long");
364+
jclass bclass = jni_find_class(env, "java/lang/Long");
365365
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(J)V");
366366
jvalue val;
367367
val.j = (int64_t)(*p_args[i]);
@@ -370,7 +370,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
370370
to_free.push_back(obj);
371371
} break;
372372
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_FLOAT: {
373-
jclass bclass = env->FindClass("java/lang/Float");
373+
jclass bclass = jni_find_class(env, "java/lang/Float");
374374
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(F)V");
375375
jvalue val;
376376
val.f = (float)(*p_args[i]);
@@ -379,7 +379,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
379379
to_free.push_back(obj);
380380
} break;
381381
case ARG_NUMBER_CLASS_BIT | ARG_TYPE_DOUBLE: {
382-
jclass bclass = env->FindClass("java/lang/Double");
382+
jclass bclass = jni_find_class(env, "java/lang/Double");
383383
jmethodID ctor = env->GetMethodID(bclass, "<init>", "(D)V");
384384
jvalue val;
385385
val.d = (double)(*p_args[i]);
@@ -572,7 +572,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
572572

573573
if (p_args[i]->get_type() == Variant::ARRAY) {
574574
Array arr = *p_args[i];
575-
a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr);
575+
a = env->NewObjectArray(arr.size(), jni_find_class(env, "java/lang/String"), nullptr);
576576
for (int j = 0; j < arr.size(); j++) {
577577
String s = arr[j];
578578
jstring jStr = env->NewStringUTF(s.utf8().get_data());
@@ -581,7 +581,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
581581
}
582582
} else if (p_args[i]->get_type() == Variant::PACKED_STRING_ARRAY) {
583583
PackedStringArray arr = *p_args[i];
584-
a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr);
584+
a = env->NewObjectArray(arr.size(), jni_find_class(env, "java/lang/String"), nullptr);
585585
for (int j = 0; j < arr.size(); j++) {
586586
String s = arr[j];
587587
jstring jStr = env->NewStringUTF(s.utf8().get_data());
@@ -595,7 +595,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
595595
} break;
596596
case ARG_ARRAY_BIT | ARG_TYPE_CALLABLE: {
597597
Array arr = *p_args[i];
598-
jobjectArray jarr = env->NewObjectArray(arr.size(), env->FindClass("org/godotengine/godot/variant/Callable"), nullptr);
598+
jobjectArray jarr = env->NewObjectArray(arr.size(), jni_find_class(env, "org/godotengine/godot/variant/Callable"), nullptr);
599599
for (int j = 0; j < arr.size(); j++) {
600600
Variant callable = arr[j];
601601
jobject jcallable = callable_to_jcallable(env, callable);
@@ -611,7 +611,7 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method,
611611
if (cn.begins_with("[L") && cn.ends_with(";")) {
612612
cn = cn.substr(2, cn.length() - 3);
613613
}
614-
jclass c = env->FindClass(cn.utf8().get_data());
614+
jclass c = jni_find_class(env, cn.utf8().get_data());
615615
if (c) {
616616
Array arr = *p_args[i];
617617
jobjectArray jarr = env->NewObjectArray(arr.size(), c, nullptr);
@@ -1470,7 +1470,7 @@ Ref<JavaClass> JavaClassWrapper::_wrap(const String &p_class, bool p_allow_priva
14701470
JNIEnv *env = get_jni_env();
14711471
ERR_FAIL_NULL_V(env, Ref<JavaClass>());
14721472

1473-
jclass bclass = env->FindClass(class_name_dots.replace_char('.', '/').utf8().get_data());
1473+
jclass bclass = jni_find_class(env, class_name_dots.replace_char('.', '/').utf8().get_data());
14741474
ERR_FAIL_NULL_V_MSG(bclass, Ref<JavaClass>(), vformat("Java class '%s' not found.", p_class));
14751475

14761476
jobjectArray constructors = (jobjectArray)env->CallObjectMethod(bclass, Class_getDeclaredConstructors);
@@ -1699,61 +1699,61 @@ JavaClassWrapper::JavaClassWrapper() {
16991699
JNIEnv *env = get_jni_env();
17001700
ERR_FAIL_NULL(env);
17011701

1702-
jclass bclass = env->FindClass("java/lang/Class");
1702+
jclass bclass = jni_find_class(env, "java/lang/Class");
17031703
Class_getDeclaredConstructors = env->GetMethodID(bclass, "getDeclaredConstructors", "()[Ljava/lang/reflect/Constructor;");
17041704
Class_getDeclaredMethods = env->GetMethodID(bclass, "getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
17051705
Class_getFields = env->GetMethodID(bclass, "getFields", "()[Ljava/lang/reflect/Field;");
17061706
Class_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
17071707
Class_getSuperclass = env->GetMethodID(bclass, "getSuperclass", "()Ljava/lang/Class;");
17081708
env->DeleteLocalRef(bclass);
17091709

1710-
bclass = env->FindClass("java/lang/reflect/Constructor");
1710+
bclass = jni_find_class(env, "java/lang/reflect/Constructor");
17111711
Constructor_getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;");
17121712
Constructor_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
17131713
env->DeleteLocalRef(bclass);
17141714

1715-
bclass = env->FindClass("java/lang/reflect/Method");
1715+
bclass = jni_find_class(env, "java/lang/reflect/Method");
17161716
Method_getParameterTypes = env->GetMethodID(bclass, "getParameterTypes", "()[Ljava/lang/Class;");
17171717
Method_getReturnType = env->GetMethodID(bclass, "getReturnType", "()Ljava/lang/Class;");
17181718
Method_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
17191719
Method_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
17201720
env->DeleteLocalRef(bclass);
17211721

1722-
bclass = env->FindClass("java/lang/reflect/Field");
1722+
bclass = jni_find_class(env, "java/lang/reflect/Field");
17231723
Field_getName = env->GetMethodID(bclass, "getName", "()Ljava/lang/String;");
17241724
Field_getModifiers = env->GetMethodID(bclass, "getModifiers", "()I");
17251725
Field_get = env->GetMethodID(bclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
17261726
env->DeleteLocalRef(bclass);
17271727

1728-
bclass = env->FindClass("java/lang/Boolean");
1728+
bclass = jni_find_class(env, "java/lang/Boolean");
17291729
Boolean_booleanValue = env->GetMethodID(bclass, "booleanValue", "()Z");
17301730
env->DeleteLocalRef(bclass);
17311731

1732-
bclass = env->FindClass("java/lang/Byte");
1732+
bclass = jni_find_class(env, "java/lang/Byte");
17331733
Byte_byteValue = env->GetMethodID(bclass, "byteValue", "()B");
17341734
env->DeleteLocalRef(bclass);
17351735

1736-
bclass = env->FindClass("java/lang/Character");
1736+
bclass = jni_find_class(env, "java/lang/Character");
17371737
Character_characterValue = env->GetMethodID(bclass, "charValue", "()C");
17381738
env->DeleteLocalRef(bclass);
17391739

1740-
bclass = env->FindClass("java/lang/Short");
1740+
bclass = jni_find_class(env, "java/lang/Short");
17411741
Short_shortValue = env->GetMethodID(bclass, "shortValue", "()S");
17421742
env->DeleteLocalRef(bclass);
17431743

1744-
bclass = env->FindClass("java/lang/Integer");
1744+
bclass = jni_find_class(env, "java/lang/Integer");
17451745
Integer_integerValue = env->GetMethodID(bclass, "intValue", "()I");
17461746
env->DeleteLocalRef(bclass);
17471747

1748-
bclass = env->FindClass("java/lang/Long");
1748+
bclass = jni_find_class(env, "java/lang/Long");
17491749
Long_longValue = env->GetMethodID(bclass, "longValue", "()J");
17501750
env->DeleteLocalRef(bclass);
17511751

1752-
bclass = env->FindClass("java/lang/Float");
1752+
bclass = jni_find_class(env, "java/lang/Float");
17531753
Float_floatValue = env->GetMethodID(bclass, "floatValue", "()F");
17541754
env->DeleteLocalRef(bclass);
17551755

1756-
bclass = env->FindClass("java/lang/Double");
1756+
bclass = jni_find_class(env, "java/lang/Double");
17571757
Double_doubleValue = env->GetMethodID(bclass, "doubleValue", "()D");
17581758
env->DeleteLocalRef(bclass);
17591759
}

platform/android/java_godot_lib_jni.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ static void _terminate(JNIEnv *env, bool p_restart = false) {
119119
FileAccessFilesystemJAndroid::terminate();
120120
NetSocketAndroid::terminate();
121121

122+
cleanup_android_class_loader();
123+
122124
if (godot_java) {
123125
godot_java->on_godot_terminating(env);
124126
if (!restart_on_cleanup) {
@@ -144,12 +146,13 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv
144146
JavaVM *jvm;
145147
env->GetJavaVM(&jvm);
146148

149+
init_thread_jandroid(jvm, env);
150+
setup_android_class_loader();
151+
147152
// create our wrapper classes
148153
godot_java = new GodotJavaWrapper(env, p_godot_instance);
149154
godot_io_java = new GodotIOJavaWrapper(env, p_godot_io);
150155

151-
init_thread_jandroid(jvm, env);
152-
153156
FileAccessAndroid::setup(p_asset_manager);
154157
DirAccessJAndroid::setup(p_directory_access_handler);
155158
FileAccessFilesystemJAndroid::setup(p_file_access_handler);
@@ -478,7 +481,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_godotengine_godot_GodotLib_getRendererIn
478481
String rendering_driver = RenderingServer::get_singleton()->get_current_rendering_driver_name();
479482
String rendering_method = RenderingServer::get_singleton()->get_current_rendering_method();
480483

481-
jobjectArray result = env->NewObjectArray(2, env->FindClass("java/lang/String"), nullptr);
484+
jobjectArray result = env->NewObjectArray(2, jni_find_class(env, "java/lang/String"), nullptr);
482485
env->SetObjectArrayElement(result, 0, env->NewStringUTF(rendering_driver.utf8().get_data()));
483486
env->SetObjectArrayElement(result, 1, env->NewStringUTF(rendering_method.utf8().get_data()));
484487

platform/android/java_godot_wrapper.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) {
4141
godot_instance = p_env->NewGlobalRef(p_godot_instance);
4242

4343
// get info about our Godot class so we can get pointers and stuff...
44-
godot_class = p_env->FindClass("org/godotengine/godot/Godot");
44+
godot_class = jni_find_class(p_env, "org/godotengine/godot/Godot");
4545
if (godot_class) {
4646
godot_class = (jclass)p_env->NewGlobalRef(godot_class);
4747
} else {
@@ -308,7 +308,7 @@ Error GodotJavaWrapper::show_dialog(const String &p_title, const String &p_descr
308308
ERR_FAIL_NULL_V(env, ERR_UNCONFIGURED);
309309
jstring j_title = env->NewStringUTF(p_title.utf8().get_data());
310310
jstring j_description = env->NewStringUTF(p_description.utf8().get_data());
311-
jobjectArray j_buttons = env->NewObjectArray(p_buttons.size(), env->FindClass("java/lang/String"), nullptr);
311+
jobjectArray j_buttons = env->NewObjectArray(p_buttons.size(), jni_find_class(env, "java/lang/String"), nullptr);
312312
for (int i = 0; i < p_buttons.size(); ++i) {
313313
jstring j_button = env->NewStringUTF(p_buttons[i].utf8().get_data());
314314
env->SetObjectArrayElement(j_buttons, i, j_button);
@@ -353,7 +353,7 @@ Error GodotJavaWrapper::show_file_picker(const String &p_current_directory, cons
353353
filters.append_array(E.get_slicec(';', 0).split(",")); // Add extensions.
354354
filters.append_array(E.get_slicec(';', 2).split(",")); // Add MIME types.
355355
}
356-
jobjectArray j_filters = env->NewObjectArray(filters.size(), env->FindClass("java/lang/String"), nullptr);
356+
jobjectArray j_filters = env->NewObjectArray(filters.size(), jni_find_class(env, "java/lang/String"), nullptr);
357357
for (int i = 0; i < filters.size(); ++i) {
358358
jstring j_filter = env->NewStringUTF(filters[i].utf8().get_data());
359359
env->SetObjectArrayElement(j_filters, i, j_filter);
@@ -469,7 +469,7 @@ int GodotJavaWrapper::create_new_godot_instance(const List<String> &args) {
469469
if (_create_new_godot_instance) {
470470
JNIEnv *env = get_jni_env();
471471
ERR_FAIL_NULL_V(env, 0);
472-
jobjectArray jargs = env->NewObjectArray(args.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
472+
jobjectArray jargs = env->NewObjectArray(args.size(), jni_find_class(env, "java/lang/String"), env->NewStringUTF(""));
473473
int i = 0;
474474
for (List<String>::ConstIterator itr = args.begin(); itr != args.end(); ++itr, ++i) {
475475
jstring j_arg = env->NewStringUTF(itr->utf8().get_data());

0 commit comments

Comments
 (0)