1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2012-2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Java related services specific to Android and its Dalvik VM
20 import native_app_glue
22 extern class JavaClassLoader in "Java" `{java.lang.ClassLoader`}
28 redef fun create_default_jvm
30 var jvm = app.native_app_glue.ndk_native_activity.vm
31 var jni_env = jvm.attach_current_thread
32 if jni_env.address_is_null then jni_env = jvm.env
35 self.jni_env = jni_env
38 private var class_loader: nullable JavaObject = null
39 private var class_loader_method: nullable JMethodID = null
40 redef fun load_jclass(name)
42 var class_loader = self.class_loader
43 if class_loader == null then
44 find_class_loader(app.native_app_glue.ndk_native_activity.java_native_activity)
45 class_loader = self.class_loader
46 assert class_loader != null
49 var class_loader_method = self.class_loader_method
50 assert class_loader_method != null
52 return load_jclass_intern(class_loader, class_loader_method, name)
55 private fun find_class_loader(native_activity: NativeActivity) import jni_env, class_loader=, JavaObject.as nullable, class_loader_method=, JMethodID.as nullable `{
56 JNIEnv *env
= Sys_jni_env(recv
);
58 // Retrieve main activity
59 jclass class_activity
= (*env
)->GetObjectClass(env
, native_activity
);
60 if (class_activity
== NULL) {
61 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retreiving activity class");
62 (*env
)->ExceptionDescribe(env
);
66 jmethodID class_activity_getClassLoader
= (*env
)->GetMethodID(env
, class_activity
, "getClassLoader", "()Ljava/lang/ClassLoader;");
67 if (class_activity_getClassLoader
== NULL) {
68 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retreiving 'getClassLoader' method");
69 (*env
)->ExceptionDescribe(env
);
73 // Call activity
.getClassLoader
74 jobject instance_class_loader
= (*env
)->CallObjectMethod(env
, native_activity
, class_activity_getClassLoader
);
75 if (instance_class_loader
== NULL) {
76 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retreiving class loader instance");
77 (*env
)->ExceptionDescribe(env
);
81 jclass class_class_loader
= (*env
)->GetObjectClass(env
, instance_class_loader
);
82 if (class_class_loader
== NULL) {
83 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retreiving class of class loader");
84 (*env
)->ExceptionDescribe(env
);
88 // Get the method
ClassLoader.findClass
89 jmethodID class_class_loader_findClass
= (*env
)->GetMethodID(env
, class_class_loader
, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
90 if (class_class_loader_findClass
== NULL) {
91 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed retreiving 'findClass' method");
92 (*env
)->ExceptionDescribe(env
);
96 // Return the values to
Nit
97 Sys_class_loader__assign(recv
, JavaObject_as_nullable((*env
)->NewGlobalRef(env
, instance_class_loader
)));
98 Sys_class_loader_method__assign(recv
, JMethodID_as_nullable(class_class_loader_findClass
));
101 (*env
)->DeleteLocalRef(env
, class_activity
);
102 (*env
)->DeleteLocalRef(env
, instance_class_loader
);
103 (*env
)->DeleteLocalRef(env
, class_class_loader
);
106 private fun load_jclass_intern(instance_class_loader: JavaObject, class_loader_findClass: JMethodID, name: NativeString): JClass import jni_env `{
107 JNIEnv *env
= Sys_jni_env(recv
);
108 jobject class_name
= (*env
)->NewStringUTF(env
, name
);
110 jclass java_class
= (*env
)->CallObjectMethod(env
, instance_class_loader
, class_loader_findClass
, class_name
);
111 if (java_class
== NULL) {
112 __android_log_print
(ANDROID_LOG_ERROR, "Nit", "Failed loading targetted class");
113 (*env
)->ExceptionDescribe(env
);
117 (*env
)->DeleteLocalRef(env
, class_name
);