tests: add engine `nitg-sg` for --semi-global
[nit.git] / lib / java.nit
index 81d22fb..de82015 100644 (file)
 # limitations under the License.
 
 # Supporting services for the FFI with Java
+#
+# This modules relies on `Sys::jvm`, `Sys::jni_env` and
+# `Sys::create_default_jvm` to get a handle on a JVM. You can adapt the
+# behavior of the FFI and services in this module by redefing
+# `Sys::create_default_jvm` and supply your own JVM object. You can manage
+# multiple java thread by switching the current environment in a redef
+# of `Sys::jni_env`, and multiple JVM using `Sys::jvm`.
+#
+# The module `jvm` gives more control over the JVM instances and wraps
+# most of JNI functions. You can use it to further customize the behavior 
+# of your code.
 module java is
        c_compiler_option("-I $(JAVA_HOME)/include/")
        c_linker_option("-L $(JNI_LIB_PATH) -ljvm")
@@ -38,7 +49,6 @@ redef class Sys
        fun jvm=(jvm: JavaVM) do jvm_cache = jvm
 
        # Current main `JniEnv`
-       # FIXME support threaded Java
        fun jni_env: JniEnv
        do
                if jni_env_cache == null then create_default_jvm
@@ -49,7 +59,7 @@ redef class Sys
        fun jni_env=(jni_env: JniEnv) do jni_env_cache = jni_env
 
        # Called by `jvm` and `jni_env` to instanciate a Java Virual Machine.
-       # Used mostly for FFI with Java.
+       # Used mostly for the FFI with Java.
        protected fun create_default_jvm
        do
                var builder = new JavaVMBuilder
@@ -63,6 +73,21 @@ redef class Sys
                self.jvm = jvm
                self.jni_env = builder.jni_env.as(not null)
        end
+
+       # Get a Java class by its name from the current `jni_env`
+       fun load_jclass(name: NativeString): JClass import jni_env `{
+               JNIEnv *nit_ffi_jni_env = Sys_jni_env(recv);
+
+               // retreive the implementation Java class
+               jclass java_class = (*nit_ffi_jni_env)->FindClass(nit_ffi_jni_env, name);
+               if (java_class == NULL) {
+                       fprintf(stderr, "Nit FFI with Java error: failed to load class.\\n");
+                       (*nit_ffi_jni_env)->ExceptionDescribe(nit_ffi_jni_env);
+                       exit(1);
+               }
+
+               return java_class;
+       `}
 end
 
 # A standard Java string `java.lang.String`
@@ -70,6 +95,9 @@ end
 # Converted to a Nit string using `to_s`, or to a C string with `to_cstring`.
 # Created using `String::to_java_string` or `NativeString::to_java_string`.
 extern class JavaString in "Java" `{ java.lang.String `}
+       super JavaObject
+
+       redef type SELF: JavaString
 
        # Get the string from Java and copy it to Nit memory
        fun to_cstring: NativeString import sys, Sys.jni_env `{
@@ -108,3 +136,31 @@ end
 redef class String
        fun to_java_string: JavaString do return to_cstring.to_java_string
 end
+
+redef extern class JavaObject
+       type SELF: JavaObject
+
+       # Returns a global reference to the Java object behind this reference
+       #
+       # You must use a global reference when keeping a Java object
+       # across execution of Java code, per JNI specification.
+       fun new_global_ref: SELF import sys, Sys.jni_env `{
+               Sys sys = JavaObject_sys(recv);
+               JNIEnv *env = Sys_jni_env(sys);
+               return (*env)->NewGlobalRef(env, recv);
+       `}
+
+       # Delete this global reference
+       fun delete_global_ref import sys, Sys.jni_env `{
+               Sys sys = JavaObject_sys(recv);
+               JNIEnv *env = Sys_jni_env(sys);
+               (*env)->DeleteGlobalRef(env, recv);
+       `}
+
+       # Delete this local reference
+       fun delete_local_ref import sys, Sys.jni_env `{
+               Sys sys = JavaObject_sys(recv);
+               JNIEnv *env = Sys_jni_env(sys);
+               (*env)->DeleteLocalRef(env, recv);
+       `}
+end