# 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")
+ cflags "-I $(JAVA_HOME)/include/ -I $(JAVA_HOME)/include/linux/"
+ ldflags "-L $(JNI_LIB_PATH) -ljvm"
new_annotation extra_java_files
end
private var jvm_cache: nullable JavaVM = null
private var jni_env_cache: nullable JniEnv = null
- # Default Java Virtual Machine to use (will be instanciated using
+ # Default Java Virtual Machine to use (will be instantiated using
# `create_default_jvm` if not already set)
fun jvm: JavaVM
do
# Sets the current default JNI env (use with `jvm=`)
fun jni_env=(jni_env: JniEnv) do jni_env_cache = jni_env
- # Called by `jvm` and `jni_env` to instanciate a Java Virual Machine.
+ # Called by `jvm` and `jni_env` to instantiate a Java Virtual Machine.
# Used mostly for the FFI with Java.
protected fun create_default_jvm
do
var builder = new JavaVMBuilder
- # By default, look for Java classes in a jar file the same dir as the executable
+ # By default, look for Java classes in a jar file the same directory as the executable
builder.options.add "-Djava.class.path={sys.program_name}.jar"
var jvm = builder.create_jvm
# 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);
+ JNIEnv *nit_ffi_jni_env = Sys_jni_env(self);
- // retreive the implementation Java class
+ // retrieve 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");
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 `{
- Sys sys = JavaString_sys(recv);
+ Sys sys = JavaString_sys(self);
JNIEnv *env = Sys_jni_env(sys);
// Get the data from Java
- const jbyte *java_cstr = (char*)(*env)->GetStringUTFChars(env, recv, NULL);
- jsize len = (*env)->GetStringUTFLength(env, recv);
+ const char *java_cstr = (*env)->GetStringUTFChars(env, self, NULL);
+ jsize len = (*env)->GetStringUTFLength(env, self);
// Copy it in control of Nit
char *nit_cstr = (char*)malloc(len+1);
nit_cstr[len] = '\0';
// Free JNI ref and return
- (*env)->ReleaseStringUTFChars(env, recv, java_cstr);
+ (*env)->ReleaseStringUTFChars(env, self, java_cstr);
return nit_cstr;
`}
# This instance is only valid until the next execution of Java code.
# You can use `new_local_ref` to keep it longer.
fun to_java_string: JavaString import sys, Sys.jni_env `{
- Sys sys = JavaString_sys(recv);
+ Sys sys = JavaString_sys(self);
JNIEnv *env = Sys_jni_env(sys);
- return (*env)->NewStringUTF(env, recv);
+ return (*env)->NewStringUTF(env, self);
`}
end
redef class Text
+ # Get `self` as a `JavaString`
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);
+ Sys sys = JavaObject_sys(self);
JNIEnv *env = Sys_jni_env(sys);
- return (*env)->NewGlobalRef(env, recv);
+ return (*env)->NewGlobalRef(env, self);
`}
# Delete this global reference
fun delete_global_ref import sys, Sys.jni_env `{
- Sys sys = JavaObject_sys(recv);
+ Sys sys = JavaObject_sys(self);
JNIEnv *env = Sys_jni_env(sys);
- (*env)->DeleteGlobalRef(env, recv);
+ (*env)->DeleteGlobalRef(env, self);
`}
# Delete this local reference
fun delete_local_ref import sys, Sys.jni_env `{
- Sys sys = JavaObject_sys(recv);
+ Sys sys = JavaObject_sys(self);
JNIEnv *env = Sys_jni_env(sys);
- (*env)->DeleteLocalRef(env, recv);
+ (*env)->DeleteLocalRef(env, self);
`}
# Pops the current local reference frame and return a valid reference to self
#
- # Similiar to `JavaVM::pop_local_frame` but returns a value.
+ # Similar to `JavaVM::pop_local_frame` but returns a value.
fun pop_from_local_frame: SELF
do
var jni_env = sys.jni_env
end
private fun pop_from_local_frame_with_env(jni_env: JniEnv): SELF `{
- return (*jni_env)->PopLocalFrame(jni_env, recv);
+ return (*jni_env)->PopLocalFrame(jni_env, self);
`}
+
+ # Is `self` null in Java?
+ #
+ # Since Java type system doesn't have the same `nullable` concept as Nit's,
+ # the two systems are not directly compatible. Any Nit instances of
+ # `JavaObject` may hold a Java null.
+ #
+ # To benefit from the safer type system of Nit, it is recommended to check
+ # the return of all extern methods implemented in Java to ensure the value
+ # is not a Java null. In case it is, you should replace it by a normal Nit
+ # `null`.
+ fun is_java_null: Bool in "Java" `{ return self == null; `}
+
+ # `JavaString` representation of `self` using Java's `toString`
+ fun to_java_string: JavaString in "Java" `{ return self.toString(); `}
+
+ # Use Java's `toString` for any `JavaObject`
+ redef fun to_s
+ do
+ if is_java_null then return super
+ return to_java_string.to_s
+ end
end