diff --git a/.gitignore b/.gitignore index e35d885..7cd1a64 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ _build +compile_commands.json +.cache/ diff --git a/bin/main.ml b/bin/main.ml index 5535c7f..7a0a016 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -8,11 +8,16 @@ let parse (path : string) = let verify (name : string) = Loader.initialize_bootstrap_loader Testclasses.test_loader; - let cls = Main.load_class name Loader.bootstrap_loader in + let cls = Loader.load_class name Loader.bootstrap_loader in let safe = Main.classIsTypeSafe cls in Printf.printf "Class %S is safe: %B\n" cls.name safe; if safe then print_endline "\027[32;1mSUCCESS!!\027[0m" +let exec (name : string) = + let jvm = Exec.Jvm.create_jvm Testclasses.test_loader in + jvm#exec_main name; + jvm#free + let () = if Array.length Sys.argv <= 2 then print_endline "usage: " else @@ -25,4 +30,7 @@ let () = | "parse" -> let _ = parse param in () - | _ -> print_endline "error: Action must be verify or parse" + | "exec" -> + let _ = exec param in + () + | _ -> print_endline "error: Action must be verify, parse, or exec" diff --git a/class/extern-lib b/class/extern-lib new file mode 120000 index 0000000..1b8a056 --- /dev/null +++ b/class/extern-lib @@ -0,0 +1 @@ +/home/rymiel/misc/java/lib \ No newline at end of file diff --git a/dune-project b/dune-project index 8a9c3cb..dcfb453 100644 --- a/dune-project +++ b/dune-project @@ -14,4 +14,3 @@ (package (name jvmilia) (depends ocaml dune)) - diff --git a/lib/dune b/lib/dune index 7dbce25..b6d42b6 100644 --- a/lib/dune +++ b/lib/dune @@ -2,4 +2,8 @@ (library (name jvmilia) - (libraries unix)) + (foreign_stubs + (language cxx) + (names native jni) + (flags -std=c++20 -fPIC)) + (libraries ctypes ctypes-foreign)) diff --git a/lib/exec/debug.ml b/lib/exec/debug.ml new file mode 100644 index 0000000..86baaa6 --- /dev/null +++ b/lib/exec/debug.ml @@ -0,0 +1,32 @@ +let indent = 2 +let depth = ref 0 + +type entry = string + +let stack = ref [] +let stack_push (v : entry) = stack := v :: !stack + +let stack_pop () : entry = + match !stack with + | [] -> failwith "Debug stack is empty" + | x :: xs -> + stack := xs; + x + +let push (ctx : string) (s : string) : unit = + print_string (String.make (!depth * indent) ' '); + print_string "\027[34m>>\027[0m "; + let prefix = Printf.sprintf "%s: %s" ctx s in + print_string prefix; + print_newline (); + stack_push prefix; + incr depth + +let pop () : unit = + let top = stack_pop () in + decr depth; + print_string (String.make (!depth * indent) ' '); + print_string "\027[34m<<\027[0m "; + print_string top; + print_newline (); + () diff --git a/lib/exec/debug.mli b/lib/exec/debug.mli new file mode 100644 index 0000000..2c8b946 --- /dev/null +++ b/lib/exec/debug.mli @@ -0,0 +1,2 @@ +val push : string -> string -> unit +val pop : unit -> unit diff --git a/lib/exec/jni.cpp b/lib/exec/jni.cpp new file mode 100644 index 0000000..cdc5cd9 --- /dev/null +++ b/lib/exec/jni.cpp @@ -0,0 +1,1073 @@ +#include "jni.h" +#include +#include +#include + +namespace jvmilia { +JVMData *getData(JNIEnv *env) { + Context *context = std::bit_cast(env); +// __builtin_dump_struct(context->data, printf); + return context->data; +} +jint GetVersion(JNIEnv *env) { + puts("Unimplemented JNI method GetVersion"); + std::exit(1); +} +jclass DefineClass(JNIEnv *env, const char *name, jobject loader, + const jbyte *buf, jsize len) { + puts("Unimplemented JNI method DefineClass"); + std::exit(1); +} +jclass FindClass(JNIEnv *env, const char *name) { + puts("Unimplemented JNI method FindClass"); + std::exit(1); +} +jmethodID FromReflectedMethod(JNIEnv *env, jobject method) { + puts("Unimplemented JNI method FromReflectedMethod"); + std::exit(1); +} +jfieldID FromReflectedField(JNIEnv *env, jobject field) { + puts("Unimplemented JNI method FromReflectedField"); + std::exit(1); +} +jobject ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID, + jboolean isStatic) { + puts("Unimplemented JNI method ToReflectedMethod"); + std::exit(1); +} +jclass GetSuperclass(JNIEnv *env, jclass sub) { + puts("Unimplemented JNI method GetSuperclass"); + std::exit(1); +} +jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup) { + puts("Unimplemented JNI method IsAssignableFrom"); + std::exit(1); +} +jobject ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, + jboolean isStatic) { + puts("Unimplemented JNI method ToReflectedField"); + std::exit(1); +} +jint Throw(JNIEnv *env, jthrowable obj) { + puts("Unimplemented JNI method Throw"); + std::exit(1); +} +jint ThrowNew(JNIEnv *env, jclass clazz, const char *msg) { + puts("Unimplemented JNI method ThrowNew"); + std::exit(1); +} +jthrowable ExceptionOccurred(JNIEnv *env) { + puts("Unimplemented JNI method ExceptionOccurred"); + std::exit(1); +} +void ExceptionDescribe(JNIEnv *env) { + puts("Unimplemented JNI method ExceptionDescribe"); + std::exit(1); +} +void ExceptionClear(JNIEnv *env) { + puts("Unimplemented JNI method ExceptionClear"); + std::exit(1); +} +void FatalError(JNIEnv *env, const char *msg) { + puts("Unimplemented JNI method FatalError"); + std::exit(1); +} +jint PushLocalFrame(JNIEnv *env, jint capacity) { + puts("Unimplemented JNI method PushLocalFrame"); + std::exit(1); +} +jobject PopLocalFrame(JNIEnv *env, jobject result) { + puts("Unimplemented JNI method PopLocalFrame"); + std::exit(1); +} +jobject NewGlobalRef(JNIEnv *env, jobject lobj) { + puts("Unimplemented JNI method NewGlobalRef"); + std::exit(1); +} +void DeleteGlobalRef(JNIEnv *env, jobject gref) { + puts("Unimplemented JNI method DeleteGlobalRef"); + std::exit(1); +} +void DeleteLocalRef(JNIEnv *env, jobject obj) { + puts("Unimplemented JNI method DeleteLocalRef"); + std::exit(1); +} +jboolean IsSameObject(JNIEnv *env, jobject obj1, jobject obj2) { + puts("Unimplemented JNI method IsSameObject"); + std::exit(1); +} +jobject NewLocalRef(JNIEnv *env, jobject ref) { + puts("Unimplemented JNI method NewLocalRef"); + std::exit(1); +} +jint EnsureLocalCapacity(JNIEnv *env, jint capacity) { + puts("Unimplemented JNI method EnsureLocalCapacity"); + std::exit(1); +} +jobject AllocObject(JNIEnv *env, jclass clazz) { + puts("Unimplemented JNI method AllocObject"); + std::exit(1); +} +jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { + puts("Unimplemented JNI method NewObject"); + std::exit(1); +} +jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method NewObjectV"); + std::exit(1); +} +jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method NewObjectA"); + std::exit(1); +} +jclass GetObjectClass(JNIEnv *env, jobject obj) { + puts("Unimplemented JNI method GetObjectClass"); + std::exit(1); +} +jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) { + puts("Unimplemented JNI method IsInstanceOf"); + std::exit(1); +} +jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { + puts("Unimplemented JNI method GetMethodID"); + std::exit(1); +} +jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallObjectMethod"); + std::exit(1); +} +jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallObjectMethodV"); + std::exit(1); +} +jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallObjectMethodA"); + std::exit(1); +} +jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallBooleanMethod"); + std::exit(1); +} +jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallBooleanMethodV"); + std::exit(1); +} +jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallBooleanMethodA"); + std::exit(1); +} +jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallByteMethod"); + std::exit(1); +} +jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallByteMethodV"); + std::exit(1); +} +jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallByteMethodA"); + std::exit(1); +} +jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallCharMethod"); + std::exit(1); +} +jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallCharMethodV"); + std::exit(1); +} +jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallCharMethodA"); + std::exit(1); +} +jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallShortMethod"); + std::exit(1); +} +jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallShortMethodV"); + std::exit(1); +} +jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallShortMethodA"); + std::exit(1); +} +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallIntMethod"); + std::exit(1); +} +jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallIntMethodV"); + std::exit(1); +} +jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallIntMethodA"); + std::exit(1); +} +jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallLongMethod"); + std::exit(1); +} +jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallLongMethodV"); + std::exit(1); +} +jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallLongMethodA"); + std::exit(1); +} +jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallFloatMethod"); + std::exit(1); +} +jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallFloatMethodV"); + std::exit(1); +} +jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallFloatMethodA"); + std::exit(1); +} +jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallDoubleMethod"); + std::exit(1); +} +jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallDoubleMethodV"); + std::exit(1); +} +jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallDoubleMethodA"); + std::exit(1); +} +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallVoidMethod"); + std::exit(1); +} +void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallVoidMethodV"); + std::exit(1); +} +void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallVoidMethodA"); + std::exit(1); +} +jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualObjectMethod"); + std::exit(1); +} +jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualObjectMethodV"); + std::exit(1); +} +jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualObjectMethodA"); + std::exit(1); +} +jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualBooleanMethod"); + std::exit(1); +} +jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualBooleanMethodV"); + std::exit(1); +} +jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualBooleanMethodA"); + std::exit(1); +} +jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualByteMethod"); + std::exit(1); +} +jbyte CallNonvirtualByteMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualByteMethodV"); + std::exit(1); +} +jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualByteMethodA"); + std::exit(1); +} +jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualCharMethod"); + std::exit(1); +} +jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualCharMethodV"); + std::exit(1); +} +jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualCharMethodA"); + std::exit(1); +} +jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualShortMethod"); + std::exit(1); +} +jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualShortMethodV"); + std::exit(1); +} +jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualShortMethodA"); + std::exit(1); +} +jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualIntMethod"); + std::exit(1); +} +jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualIntMethodV"); + std::exit(1); +} +jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualIntMethodA"); + std::exit(1); +} +jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualLongMethod"); + std::exit(1); +} +jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualLongMethodV"); + std::exit(1); +} +jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualLongMethodA"); + std::exit(1); +} +jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualFloatMethod"); + std::exit(1); +} +jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualFloatMethodV"); + std::exit(1); +} +jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualFloatMethodA"); + std::exit(1); +} +jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualDoubleMethod"); + std::exit(1); +} +jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualDoubleMethodV"); + std::exit(1); +} +jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualDoubleMethodA"); + std::exit(1); +} +void CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...) { + puts("Unimplemented JNI method CallNonvirtualVoidMethod"); + std::exit(1); +} +void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + puts("Unimplemented JNI method CallNonvirtualVoidMethodV"); + std::exit(1); +} +void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args) { + puts("Unimplemented JNI method CallNonvirtualVoidMethodA"); + std::exit(1); +} +jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { + puts("Unimplemented JNI method GetFieldID"); + std::exit(1); +} +jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetObjectField"); + std::exit(1); +} +jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetBooleanField"); + std::exit(1); +} +jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetByteField"); + std::exit(1); +} +jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetCharField"); + std::exit(1); +} +jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetShortField"); + std::exit(1); +} +jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetIntField"); + std::exit(1); +} +jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetLongField"); + std::exit(1); +} +jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetFloatField"); + std::exit(1); +} +jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID) { + puts("Unimplemented JNI method GetDoubleField"); + std::exit(1); +} +void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val) { + puts("Unimplemented JNI method SetObjectField"); + std::exit(1); +} +void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val) { + puts("Unimplemented JNI method SetBooleanField"); + std::exit(1); +} +void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val) { + puts("Unimplemented JNI method SetByteField"); + std::exit(1); +} +void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val) { + puts("Unimplemented JNI method SetCharField"); + std::exit(1); +} +void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val) { + puts("Unimplemented JNI method SetShortField"); + std::exit(1); +} +void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint val) { + puts("Unimplemented JNI method SetIntField"); + std::exit(1); +} +void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val) { + puts("Unimplemented JNI method SetLongField"); + std::exit(1); +} +void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val) { + puts("Unimplemented JNI method SetFloatField"); + std::exit(1); +} +void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val) { + puts("Unimplemented JNI method SetDoubleField"); + std::exit(1); +} +jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { + puts("Unimplemented JNI method GetStaticMethodID"); + std::exit(1); +} +jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...) { + puts("Unimplemented JNI method CallStaticObjectMethod"); + std::exit(1); +} +jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticObjectMethodV"); + std::exit(1); +} +jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticObjectMethodA"); + std::exit(1); +} +jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...) { + puts("Unimplemented JNI method CallStaticBooleanMethod"); + std::exit(1); +} +jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticBooleanMethodV"); + std::exit(1); +} +jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticBooleanMethodA"); + std::exit(1); +} +jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallStaticByteMethod"); + std::exit(1); +} +jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticByteMethodV"); + std::exit(1); +} +jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticByteMethodA"); + std::exit(1); +} +jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallStaticCharMethod"); + std::exit(1); +} +jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticCharMethodV"); + std::exit(1); +} +jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticCharMethodA"); + std::exit(1); +} +jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...) { + puts("Unimplemented JNI method CallStaticShortMethod"); + std::exit(1); +} +jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticShortMethodV"); + std::exit(1); +} +jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticShortMethodA"); + std::exit(1); +} +jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallStaticIntMethod"); + std::exit(1); +} +jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticIntMethodV"); + std::exit(1); +} +jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticIntMethodA"); + std::exit(1); +} +jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallStaticLongMethod"); + std::exit(1); +} +jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticLongMethodV"); + std::exit(1); +} +jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticLongMethodA"); + std::exit(1); +} +jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...) { + puts("Unimplemented JNI method CallStaticFloatMethod"); + std::exit(1); +} +jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticFloatMethodV"); + std::exit(1); +} +jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticFloatMethodA"); + std::exit(1); +} +jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...) { + puts("Unimplemented JNI method CallStaticDoubleMethod"); + std::exit(1); +} +jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticDoubleMethodV"); + std::exit(1); +} +jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticDoubleMethodA"); + std::exit(1); +} +void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...) { + puts("Unimplemented JNI method CallStaticVoidMethod"); + std::exit(1); +} +void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, + va_list args) { + puts("Unimplemented JNI method CallStaticVoidMethodV"); + std::exit(1); +} +void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, + const jvalue *args) { + puts("Unimplemented JNI method CallStaticVoidMethodA"); + std::exit(1); +} +jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { + puts("Unimplemented JNI method GetStaticFieldID"); + std::exit(1); +} +jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticObjectField"); + std::exit(1); +} +jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticBooleanField"); + std::exit(1); +} +jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticByteField"); + std::exit(1); +} +jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticCharField"); + std::exit(1); +} +jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticShortField"); + std::exit(1); +} +jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticIntField"); + std::exit(1); +} +jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticLongField"); + std::exit(1); +} +jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticFloatField"); + std::exit(1); +} +jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID) { + puts("Unimplemented JNI method GetStaticDoubleField"); + std::exit(1); +} +void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jobject value) { + puts("Unimplemented JNI method SetStaticObjectField"); + std::exit(1); +} +void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jboolean value) { + puts("Unimplemented JNI method SetStaticBooleanField"); + std::exit(1); +} +void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jbyte value) { + puts("Unimplemented JNI method SetStaticByteField"); + std::exit(1); +} +void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jchar value) { + puts("Unimplemented JNI method SetStaticCharField"); + std::exit(1); +} +void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jshort value) { + puts("Unimplemented JNI method SetStaticShortField"); + std::exit(1); +} +void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jint value) { + puts("Unimplemented JNI method SetStaticIntField"); + std::exit(1); +} +void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jlong value) { + puts("Unimplemented JNI method SetStaticLongField"); + std::exit(1); +} +void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jfloat value) { + puts("Unimplemented JNI method SetStaticFloatField"); + std::exit(1); +} +void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jdouble value) { + puts("Unimplemented JNI method SetStaticDoubleField"); + std::exit(1); +} +jstring NewString(JNIEnv *env, const jchar *unicode, jsize len) { + puts("Unimplemented JNI method NewString"); + std::exit(1); +} +jsize GetStringLength(JNIEnv *env, jstring str) { + puts("Unimplemented JNI method GetStringLength"); + std::exit(1); +} +const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy) { + puts("Unimplemented JNI method GetStringChars"); + std::exit(1); +} +void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars) { + puts("Unimplemented JNI method ReleaseStringChars"); + std::exit(1); +} +jstring NewStringUTF(JNIEnv *env, const char *utf) { + puts("Unimplemented JNI method NewStringUTF"); + std::exit(1); +} +jsize GetStringUTFLength(JNIEnv *env, jstring str) { + puts("Unimplemented JNI method GetStringUTFLength"); + std::exit(1); +} +const char *GetStringUTFChars(JNIEnv *env, jstring str, jboolean *isCopy) { + puts("Unimplemented JNI method GetStringUTFChars"); + std::exit(1); +} +void ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars) { + puts("Unimplemented JNI method ReleaseStringUTFChars"); + std::exit(1); +} +jsize GetArrayLength(JNIEnv *env, jarray array) { + puts("Unimplemented JNI method GetArrayLength"); + std::exit(1); +} +jobjectArray NewObjectArray(JNIEnv *env, jsize len, jclass clazz, + jobject init) { + puts("Unimplemented JNI method NewObjectArray"); + std::exit(1); +} +jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) { + puts("Unimplemented JNI method GetObjectArrayElement"); + std::exit(1); +} +void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, + jobject val) { + puts("Unimplemented JNI method SetObjectArrayElement"); + std::exit(1); +} +jbooleanArray NewBooleanArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewBooleanArray"); + std::exit(1); +} +jbyteArray NewByteArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewByteArray"); + std::exit(1); +} +jcharArray NewCharArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewCharArray"); + std::exit(1); +} +jshortArray NewShortArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewShortArray"); + std::exit(1); +} +jintArray NewIntArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewIntArray"); + std::exit(1); +} +jlongArray NewLongArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewLongArray"); + std::exit(1); +} +jfloatArray NewFloatArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewFloatArray"); + std::exit(1); +} +jdoubleArray NewDoubleArray(JNIEnv *env, jsize len) { + puts("Unimplemented JNI method NewDoubleArray"); + std::exit(1); +} +jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *isCopy) { + puts("Unimplemented JNI method GetBooleanArrayElements"); + std::exit(1); +} +jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) { + puts("Unimplemented JNI method GetByteArrayElements"); + std::exit(1); +} +jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy) { + puts("Unimplemented JNI method GetCharArrayElements"); + std::exit(1); +} +jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, + jboolean *isCopy) { + puts("Unimplemented JNI method GetShortArrayElements"); + std::exit(1); +} +jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy) { + puts("Unimplemented JNI method GetIntArrayElements"); + std::exit(1); +} +jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy) { + puts("Unimplemented JNI method GetLongArrayElements"); + std::exit(1); +} +jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, + jboolean *isCopy) { + puts("Unimplemented JNI method GetFloatArrayElements"); + std::exit(1); +} +jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jboolean *isCopy) { + puts("Unimplemented JNI method GetDoubleArrayElements"); + std::exit(1); +} +void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *elems, jint mode) { + puts("Unimplemented JNI method ReleaseBooleanArrayElements"); + std::exit(1); +} +void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, + jint mode) { + puts("Unimplemented JNI method ReleaseByteArrayElements"); + std::exit(1); +} +void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems, + jint mode) { + puts("Unimplemented JNI method ReleaseCharArrayElements"); + std::exit(1); +} +void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems, + jint mode) { + puts("Unimplemented JNI method ReleaseShortArrayElements"); + std::exit(1); +} +void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems, + jint mode) { + puts("Unimplemented JNI method ReleaseIntArrayElements"); + std::exit(1); +} +void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems, + jint mode) { + puts("Unimplemented JNI method ReleaseLongArrayElements"); + std::exit(1); +} +void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, + jint mode) { + puts("Unimplemented JNI method ReleaseFloatArrayElements"); + std::exit(1); +} +void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array, jdouble *elems, + jint mode) { + puts("Unimplemented JNI method ReleaseDoubleArrayElements"); + std::exit(1); +} +void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize l, jboolean *buf) { + puts("Unimplemented JNI method GetBooleanArrayRegion"); + std::exit(1); +} +void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf) { + puts("Unimplemented JNI method GetByteArrayRegion"); + std::exit(1); +} +void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf) { + puts("Unimplemented JNI method GetCharArrayRegion"); + std::exit(1); +} +void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, + jshort *buf) { + puts("Unimplemented JNI method GetShortArrayRegion"); + std::exit(1); +} +void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf) { + puts("Unimplemented JNI method GetIntArrayRegion"); + std::exit(1); +} +void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, + jlong *buf) { + puts("Unimplemented JNI method GetLongArrayRegion"); + std::exit(1); +} +void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, + jfloat *buf) { + puts("Unimplemented JNI method GetFloatArrayRegion"); + std::exit(1); +} +void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf) { + puts("Unimplemented JNI method GetDoubleArrayRegion"); + std::exit(1); +} +void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize l, const jboolean *buf) { + puts("Unimplemented JNI method SetBooleanArrayRegion"); + std::exit(1); +} +void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + const jbyte *buf) { + puts("Unimplemented JNI method SetByteArrayRegion"); + std::exit(1); +} +void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + const jchar *buf) { + puts("Unimplemented JNI method SetCharArrayRegion"); + std::exit(1); +} +void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, + const jshort *buf) { + puts("Unimplemented JNI method SetShortArrayRegion"); + std::exit(1); +} +void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + const jint *buf) { + puts("Unimplemented JNI method SetIntArrayRegion"); + std::exit(1); +} +void SetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, + const jlong *buf) { + puts("Unimplemented JNI method SetLongArrayRegion"); + std::exit(1); +} +void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, + const jfloat *buf) { + puts("Unimplemented JNI method SetFloatArrayRegion"); + std::exit(1); +} +void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, const jdouble *buf) { + puts("Unimplemented JNI method SetDoubleArrayRegion"); + std::exit(1); +} +jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods) { + auto *data = getData(env); + for (int i = 0; i < nMethods; i++) { + auto method = methods[i]; + auto key = std::string(method.name) + ";" + method.signature; + data->registered_natives.insert_or_assign(key, method.fnPtr); + } + + for (auto [k, v] : data->registered_natives) { + printf("%s -> %p\n", k.data(), v); + } + + return 0; +} +jint UnregisterNatives(JNIEnv *env, jclass clazz) { + puts("Unimplemented JNI method UnregisterNatives"); + std::exit(1); +} +jint MonitorEnter(JNIEnv *env, jobject obj) { + puts("Unimplemented JNI method MonitorEnter"); + std::exit(1); +} +jint MonitorExit(JNIEnv *env, jobject obj) { + puts("Unimplemented JNI method MonitorExit"); + std::exit(1); +} +jint GetJavaVM(JNIEnv *env, JavaVM **vm) { + puts("Unimplemented JNI method GetJavaVM"); + std::exit(1); +} +void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, + jchar *buf) { + puts("Unimplemented JNI method GetStringRegion"); + std::exit(1); +} +void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, + char *buf) { + puts("Unimplemented JNI method GetStringUTFRegion"); + std::exit(1); +} +void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy) { + puts("Unimplemented JNI method GetPrimitiveArrayCritical"); + std::exit(1); +} +void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, + jint mode) { + puts("Unimplemented JNI method ReleasePrimitiveArrayCritical"); + std::exit(1); +} +const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy) { + puts("Unimplemented JNI method GetStringCritical"); + std::exit(1); +} +void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring) { + puts("Unimplemented JNI method ReleaseStringCritical"); + std::exit(1); +} +jweak NewWeakGlobalRef(JNIEnv *env, jobject obj) { + puts("Unimplemented JNI method NewWeakGlobalRef"); + std::exit(1); +} +void DeleteWeakGlobalRef(JNIEnv *env, jweak ref) { + puts("Unimplemented JNI method DeleteWeakGlobalRef"); + std::exit(1); +} +jboolean ExceptionCheck(JNIEnv *env) { + puts("Unimplemented JNI method ExceptionCheck"); + std::exit(1); +} +jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity) { + puts("Unimplemented JNI method NewDirectByteBuffer"); + std::exit(1); +} +void *GetDirectBufferAddress(JNIEnv *env, jobject buf) { + puts("Unimplemented JNI method GetDirectBufferAddress"); + std::exit(1); +} +jlong GetDirectBufferCapacity(JNIEnv *env, jobject buf) { + puts("Unimplemented JNI method GetDirectBufferCapacity"); + std::exit(1); +} +jobjectRefType GetObjectRefType(JNIEnv *env, jobject obj) { + puts("Unimplemented JNI method GetObjectRefType"); + std::exit(1); +} +jobject GetModule(JNIEnv *env, jclass clazz) { + puts("Unimplemented JNI method GetModule"); + std::exit(1); +} +jboolean IsVirtualThread(JNIEnv *env, jobject obj) { + puts("Unimplemented JNI method IsVirtualThread"); + std::exit(1); +} +} // namespace jvmilia \ No newline at end of file diff --git a/lib/exec/jni.h b/lib/exec/jni.h new file mode 100644 index 0000000..19e215c --- /dev/null +++ b/lib/exec/jni.h @@ -0,0 +1,911 @@ +#pragma once + +#include +#include +#include +extern "C" { + +using JNIEnv = const struct JNINativeInterface *; +using jint = int; +using jlong = long; +using jboolean = unsigned char; +using jbyte = signed char; +using jsize = jint; +using jchar = unsigned short; +using jshort = short; +using jfloat = float; +using jdouble = double; + +class _jobject {}; +class _jclass : public _jobject {}; +class _jthrowable : public _jobject {}; +class _jstring : public _jobject {}; +class _jarray : public _jobject {}; +class _jbooleanArray : public _jarray {}; +class _jbyteArray : public _jarray {}; +class _jcharArray : public _jarray {}; +class _jshortArray : public _jarray {}; +class _jintArray : public _jarray {}; +class _jlongArray : public _jarray {}; +class _jfloatArray : public _jarray {}; +class _jdoubleArray : public _jarray {}; +class _jobjectArray : public _jarray {}; + +using jobject = _jobject *; +using jclass = _jclass *; +using jthrowable = _jthrowable *; +using jstring = _jstring *; +using jarray = _jarray *; +using jbooleanArray = _jbooleanArray *; +using jbyteArray = _jbyteArray *; +using jcharArray = _jcharArray *; +using jshortArray = _jshortArray *; +using jintArray = _jintArray *; +using jlongArray = _jlongArray *; +using jfloatArray = _jfloatArray *; +using jdoubleArray = _jdoubleArray *; +using jobjectArray = _jobjectArray *; + +using jweak = jobject; + +struct _jmethodID; +using jmethodID = _jmethodID *; +struct _jfieldID; +using jfieldID = _jfieldID *; + +union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +}; + +struct JNINativeMethod { + char *name; + char *signature; + void *fnPtr; +}; + +struct JavaVM_; +using JavaVM = JavaVM_ *; + +enum jobjectRefType { + JNIInvalidRefType = 0, + JNILocalRefType = 1, + JNIGlobalRefType = 2, + JNIWeakGlobalRefType = 3 +}; + +struct JNINativeInterface { + void *reserved0; + void *reserved1; + void *reserved2; + + void *reserved3; + jint (*GetVersion)(JNIEnv *env); + + jclass (*DefineClass)(JNIEnv *env, const char *name, jobject loader, + const jbyte *buf, jsize len); + jclass (*FindClass)(JNIEnv *env, const char *name); + + jmethodID (*FromReflectedMethod)(JNIEnv *env, jobject method); + jfieldID (*FromReflectedField)(JNIEnv *env, jobject field); + + jobject (*ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodID, + jboolean isStatic); + + jclass (*GetSuperclass)(JNIEnv *env, jclass sub); + jboolean (*IsAssignableFrom)(JNIEnv *env, jclass sub, jclass sup); + + jobject (*ToReflectedField)(JNIEnv *env, jclass cls, jfieldID fieldID, + jboolean isStatic); + + jint (*Throw)(JNIEnv *env, jthrowable obj); + jint (*ThrowNew)(JNIEnv *env, jclass clazz, const char *msg); + jthrowable (*ExceptionOccurred)(JNIEnv *env); + void (*ExceptionDescribe)(JNIEnv *env); + void (*ExceptionClear)(JNIEnv *env); + void (*FatalError)(JNIEnv *env, const char *msg); + + jint (*PushLocalFrame)(JNIEnv *env, jint capacity); + jobject (*PopLocalFrame)(JNIEnv *env, jobject result); + + jobject (*NewGlobalRef)(JNIEnv *env, jobject lobj); + void (*DeleteGlobalRef)(JNIEnv *env, jobject gref); + void (*DeleteLocalRef)(JNIEnv *env, jobject obj); + jboolean (*IsSameObject)(JNIEnv *env, jobject obj1, jobject obj2); + jobject (*NewLocalRef)(JNIEnv *env, jobject ref); + jint (*EnsureLocalCapacity)(JNIEnv *env, jint capacity); + + jobject (*AllocObject)(JNIEnv *env, jclass clazz); + jobject (*NewObject)(JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jobject (*NewObjectV)(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); + jobject (*NewObjectA)(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); + + jclass (*GetObjectClass)(JNIEnv *env, jobject obj); + jboolean (*IsInstanceOf)(JNIEnv *env, jobject obj, jclass clazz); + + jmethodID (*GetMethodID)(JNIEnv *env, jclass clazz, const char *name, + const char *sig); + + jobject (*CallObjectMethod)(JNIEnv *env, jobject obj, jmethodID methodID, + ...); + jobject (*CallObjectMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jobject (*CallObjectMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jboolean (*CallBooleanMethod)(JNIEnv *env, jobject obj, jmethodID methodID, + ...); + jboolean (*CallBooleanMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jboolean (*CallBooleanMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jbyte (*CallByteMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); + jbyte (*CallByteMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jbyte (*CallByteMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jchar (*CallCharMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); + jchar (*CallCharMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jchar (*CallCharMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jshort (*CallShortMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); + jshort (*CallShortMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jshort (*CallShortMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jint (*CallIntMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); + jint (*CallIntMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jint (*CallIntMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jlong (*CallLongMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); + jlong (*CallLongMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jlong (*CallLongMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jfloat (*CallFloatMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); + jfloat (*CallFloatMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jfloat (*CallFloatMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jdouble (*CallDoubleMethod)(JNIEnv *env, jobject obj, jmethodID methodID, + ...); + jdouble (*CallDoubleMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + jdouble (*CallDoubleMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + void (*CallVoidMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...); + void (*CallVoidMethodV)(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); + void (*CallVoidMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); + + jobject (*CallNonvirtualObjectMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jobject (*CallNonvirtualObjectMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jobject (*CallNonvirtualObjectMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, + const jvalue *args); + + jboolean (*CallNonvirtualBooleanMethod)(JNIEnv *env, jobject obj, + jclass clazz, jmethodID methodID, + ...); + jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv *env, jobject obj, + jclass clazz, jmethodID methodID, + va_list args); + jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv *env, jobject obj, + jclass clazz, jmethodID methodID, + const jvalue *args); + + jbyte (*CallNonvirtualByteMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jbyte (*CallNonvirtualByteMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jbyte (*CallNonvirtualByteMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); + + jchar (*CallNonvirtualCharMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jchar (*CallNonvirtualCharMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jchar (*CallNonvirtualCharMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); + + jshort (*CallNonvirtualShortMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jshort (*CallNonvirtualShortMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jshort (*CallNonvirtualShortMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); + + jint (*CallNonvirtualIntMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jint (*CallNonvirtualIntMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jint (*CallNonvirtualIntMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); + + jlong (*CallNonvirtualLongMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jlong (*CallNonvirtualLongMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jlong (*CallNonvirtualLongMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); + + jfloat (*CallNonvirtualFloatMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jfloat (*CallNonvirtualFloatMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jfloat (*CallNonvirtualFloatMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); + + jdouble (*CallNonvirtualDoubleMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, + const jvalue *args); + + void (*CallNonvirtualVoidMethod)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); + void (*CallNonvirtualVoidMethodV)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); + void (*CallNonvirtualVoidMethodA)(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); + + jfieldID (*GetFieldID)(JNIEnv *env, jclass clazz, const char *name, + const char *sig); + + jobject (*GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jboolean (*GetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jbyte (*GetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jchar (*GetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jshort (*GetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jint (*GetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jlong (*GetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jfloat (*GetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID); + jdouble (*GetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID); + + void (*SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, + jobject val); + void (*SetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID, + jboolean val); + void (*SetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); + void (*SetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val); + void (*SetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val); + void (*SetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID, jint val); + void (*SetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val); + void (*SetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val); + void (*SetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID, + jdouble val); + + jmethodID (*GetStaticMethodID)(JNIEnv *env, jclass clazz, const char *name, + const char *sig); + + jobject (*CallStaticObjectMethod)(JNIEnv *env, jclass clazz, + jmethodID methodID, ...); + jobject (*CallStaticObjectMethodV)(JNIEnv *env, jclass clazz, + jmethodID methodID, va_list args); + jobject (*CallStaticObjectMethodA)(JNIEnv *env, jclass clazz, + jmethodID methodID, const jvalue *args); + + jboolean (*CallStaticBooleanMethod)(JNIEnv *env, jclass clazz, + jmethodID methodID, ...); + jboolean (*CallStaticBooleanMethodV)(JNIEnv *env, jclass clazz, + jmethodID methodID, va_list args); + jboolean (*CallStaticBooleanMethodA)(JNIEnv *env, jclass clazz, + jmethodID methodID, const jvalue *args); + + jbyte (*CallStaticByteMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); + jbyte (*CallStaticByteMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); + jbyte (*CallStaticByteMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); + + jchar (*CallStaticCharMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); + jchar (*CallStaticCharMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); + jchar (*CallStaticCharMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); + + jshort (*CallStaticShortMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); + jshort (*CallStaticShortMethodV)(JNIEnv *env, jclass clazz, + jmethodID methodID, va_list args); + jshort (*CallStaticShortMethodA)(JNIEnv *env, jclass clazz, + jmethodID methodID, const jvalue *args); + + jint (*CallStaticIntMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); + jint (*CallStaticIntMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); + jint (*CallStaticIntMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); + + jlong (*CallStaticLongMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); + jlong (*CallStaticLongMethodV)(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); + jlong (*CallStaticLongMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); + + jfloat (*CallStaticFloatMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); + jfloat (*CallStaticFloatMethodV)(JNIEnv *env, jclass clazz, + jmethodID methodID, va_list args); + jfloat (*CallStaticFloatMethodA)(JNIEnv *env, jclass clazz, + jmethodID methodID, const jvalue *args); + + jdouble (*CallStaticDoubleMethod)(JNIEnv *env, jclass clazz, + jmethodID methodID, ...); + jdouble (*CallStaticDoubleMethodV)(JNIEnv *env, jclass clazz, + jmethodID methodID, va_list args); + jdouble (*CallStaticDoubleMethodA)(JNIEnv *env, jclass clazz, + jmethodID methodID, const jvalue *args); + + void (*CallStaticVoidMethod)(JNIEnv *env, jclass cls, jmethodID methodID, + ...); + void (*CallStaticVoidMethodV)(JNIEnv *env, jclass cls, jmethodID methodID, + va_list args); + void (*CallStaticVoidMethodA)(JNIEnv *env, jclass cls, jmethodID methodID, + const jvalue *args); + + jfieldID (*GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name, + const char *sig); + jobject (*GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + jboolean (*GetStaticBooleanField)(JNIEnv *env, jclass clazz, + jfieldID fieldID); + jbyte (*GetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + jchar (*GetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + jshort (*GetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + jint (*GetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + jlong (*GetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + jfloat (*GetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + jdouble (*GetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID); + + void (*SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jobject value); + void (*SetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jboolean value); + void (*SetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jbyte value); + void (*SetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jchar value); + void (*SetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jshort value); + void (*SetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jint value); + void (*SetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jlong value); + void (*SetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jfloat value); + void (*SetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID, + jdouble value); + + jstring (*NewString)(JNIEnv *env, const jchar *unicode, jsize len); + jsize (*GetStringLength)(JNIEnv *env, jstring str); + const jchar *(*GetStringChars)(JNIEnv *env, jstring str, jboolean *isCopy); + void (*ReleaseStringChars)(JNIEnv *env, jstring str, const jchar *chars); + + jstring (*NewStringUTF)(JNIEnv *env, const char *utf); + jsize (*GetStringUTFLength)(JNIEnv *env, jstring str); + const char *(*GetStringUTFChars)(JNIEnv *env, jstring str, jboolean *isCopy); + void (*ReleaseStringUTFChars)(JNIEnv *env, jstring str, const char *chars); + + jsize (*GetArrayLength)(JNIEnv *env, jarray array); + + jobjectArray (*NewObjectArray)(JNIEnv *env, jsize len, jclass clazz, + jobject init); + jobject (*GetObjectArrayElement)(JNIEnv *env, jobjectArray array, + jsize index); + void (*SetObjectArrayElement)(JNIEnv *env, jobjectArray array, jsize index, + jobject val); + + jbooleanArray (*NewBooleanArray)(JNIEnv *env, jsize len); + jbyteArray (*NewByteArray)(JNIEnv *env, jsize len); + jcharArray (*NewCharArray)(JNIEnv *env, jsize len); + jshortArray (*NewShortArray)(JNIEnv *env, jsize len); + jintArray (*NewIntArray)(JNIEnv *env, jsize len); + jlongArray (*NewLongArray)(JNIEnv *env, jsize len); + jfloatArray (*NewFloatArray)(JNIEnv *env, jsize len); + jdoubleArray (*NewDoubleArray)(JNIEnv *env, jsize len); + + jboolean *(*GetBooleanArrayElements)(JNIEnv *env, jbooleanArray array, + jboolean *isCopy); + jbyte *(*GetByteArrayElements)(JNIEnv *env, jbyteArray array, + jboolean *isCopy); + jchar *(*GetCharArrayElements)(JNIEnv *env, jcharArray array, + jboolean *isCopy); + jshort *(*GetShortArrayElements)(JNIEnv *env, jshortArray array, + jboolean *isCopy); + jint *(*GetIntArrayElements)(JNIEnv *env, jintArray array, jboolean *isCopy); + jlong *(*GetLongArrayElements)(JNIEnv *env, jlongArray array, + jboolean *isCopy); + jfloat *(*GetFloatArrayElements)(JNIEnv *env, jfloatArray array, + jboolean *isCopy); + jdouble *(*GetDoubleArrayElements)(JNIEnv *env, jdoubleArray array, + jboolean *isCopy); + + void (*ReleaseBooleanArrayElements)(JNIEnv *env, jbooleanArray array, + jboolean *elems, jint mode); + void (*ReleaseByteArrayElements)(JNIEnv *env, jbyteArray array, jbyte *elems, + jint mode); + void (*ReleaseCharArrayElements)(JNIEnv *env, jcharArray array, jchar *elems, + jint mode); + void (*ReleaseShortArrayElements)(JNIEnv *env, jshortArray array, + jshort *elems, jint mode); + void (*ReleaseIntArrayElements)(JNIEnv *env, jintArray array, jint *elems, + jint mode); + void (*ReleaseLongArrayElements)(JNIEnv *env, jlongArray array, jlong *elems, + jint mode); + void (*ReleaseFloatArrayElements)(JNIEnv *env, jfloatArray array, + jfloat *elems, jint mode); + void (*ReleaseDoubleArrayElements)(JNIEnv *env, jdoubleArray array, + jdouble *elems, jint mode); + + void (*GetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array, jsize start, + jsize l, jboolean *buf); + void (*GetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, + jsize len, jbyte *buf); + void (*GetCharArrayRegion)(JNIEnv *env, jcharArray array, jsize start, + jsize len, jchar *buf); + void (*GetShortArrayRegion)(JNIEnv *env, jshortArray array, jsize start, + jsize len, jshort *buf); + void (*GetIntArrayRegion)(JNIEnv *env, jintArray array, jsize start, + jsize len, jint *buf); + void (*GetLongArrayRegion)(JNIEnv *env, jlongArray array, jsize start, + jsize len, jlong *buf); + void (*GetFloatArrayRegion)(JNIEnv *env, jfloatArray array, jsize start, + jsize len, jfloat *buf); + void (*GetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf); + + void (*SetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array, jsize start, + jsize l, const jboolean *buf); + void (*SetByteArrayRegion)(JNIEnv *env, jbyteArray array, jsize start, + jsize len, const jbyte *buf); + void (*SetCharArrayRegion)(JNIEnv *env, jcharArray array, jsize start, + jsize len, const jchar *buf); + void (*SetShortArrayRegion)(JNIEnv *env, jshortArray array, jsize start, + jsize len, const jshort *buf); + void (*SetIntArrayRegion)(JNIEnv *env, jintArray array, jsize start, + jsize len, const jint *buf); + void (*SetLongArrayRegion)(JNIEnv *env, jlongArray array, jsize start, + jsize len, const jlong *buf); + void (*SetFloatArrayRegion)(JNIEnv *env, jfloatArray array, jsize start, + jsize len, const jfloat *buf); + void (*SetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, const jdouble *buf); + + jint (*RegisterNatives)(JNIEnv *env, jclass clazz, + const JNINativeMethod *methods, jint nMethods); + jint (*UnregisterNatives)(JNIEnv *env, jclass clazz); + + jint (*MonitorEnter)(JNIEnv *env, jobject obj); + jint (*MonitorExit)(JNIEnv *env, jobject obj); + + jint (*GetJavaVM)(JNIEnv *env, JavaVM **vm); + + void (*GetStringRegion)(JNIEnv *env, jstring str, jsize start, jsize len, + jchar *buf); + void (*GetStringUTFRegion)(JNIEnv *env, jstring str, jsize start, jsize len, + char *buf); + + void *(*GetPrimitiveArrayCritical)(JNIEnv *env, jarray array, + jboolean *isCopy); + void (*ReleasePrimitiveArrayCritical)(JNIEnv *env, jarray array, void *carray, + jint mode); + + const jchar *(*GetStringCritical)(JNIEnv *env, jstring string, + jboolean *isCopy); + void (*ReleaseStringCritical)(JNIEnv *env, jstring string, + const jchar *cstring); + + jweak (*NewWeakGlobalRef)(JNIEnv *env, jobject obj); + void (*DeleteWeakGlobalRef)(JNIEnv *env, jweak ref); + + jboolean (*ExceptionCheck)(JNIEnv *env); + + jobject (*NewDirectByteBuffer)(JNIEnv *env, void *address, jlong capacity); + void *(*GetDirectBufferAddress)(JNIEnv *env, jobject buf); + jlong (*GetDirectBufferCapacity)(JNIEnv *env, jobject buf); + + /* New JNI 1.6 Features */ + + jobjectRefType (*GetObjectRefType)(JNIEnv *env, jobject obj); + + /* Module Features */ + + jobject (*GetModule)(JNIEnv *env, jclass clazz); + + /* Virtual threads */ + + jboolean (*IsVirtualThread)(JNIEnv *env, jobject obj); +}; +} + +namespace jvmilia { +struct JVMData { + std::unordered_map registered_natives; +}; + +struct Context { + const JNINativeInterface *interface; + JVMData *data; +}; + +jint GetVersion(JNIEnv *env); +jclass DefineClass(JNIEnv *env, const char *name, jobject loader, + const jbyte *buf, jsize len); +jclass FindClass(JNIEnv *env, const char *name); +jmethodID FromReflectedMethod(JNIEnv *env, jobject method); +jfieldID FromReflectedField(JNIEnv *env, jobject field); +jobject ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID, + jboolean isStatic); +jclass GetSuperclass(JNIEnv *env, jclass sub); +jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup); +jobject ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, + jboolean isStatic); +jint Throw(JNIEnv *env, jthrowable obj); +jint ThrowNew(JNIEnv *env, jclass clazz, const char *msg); +jthrowable ExceptionOccurred(JNIEnv *env); +void ExceptionDescribe(JNIEnv *env); +void ExceptionClear(JNIEnv *env); +void FatalError(JNIEnv *env, const char *msg); +jint PushLocalFrame(JNIEnv *env, jint capacity); +jobject PopLocalFrame(JNIEnv *env, jobject result); +jobject NewGlobalRef(JNIEnv *env, jobject lobj); +void DeleteGlobalRef(JNIEnv *env, jobject gref); +void DeleteLocalRef(JNIEnv *env, jobject obj); +jboolean IsSameObject(JNIEnv *env, jobject obj1, jobject obj2); +jobject NewLocalRef(JNIEnv *env, jobject ref); +jint EnsureLocalCapacity(JNIEnv *env, jint capacity); +jobject AllocObject(JNIEnv *env, jclass clazz); +jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...); +jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); +jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jclass GetObjectClass(JNIEnv *env, jobject obj); +jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz); +jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, + const char *sig); +jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args); +jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...); +void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, + va_list args); +void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, + const jvalue *args); +jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jbyte CallNonvirtualByteMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +void CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, ...); +void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, va_list args); +void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, + jmethodID methodID, const jvalue *args); +jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, + const char *sig); +jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID); +jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID); +jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID); +jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID); +jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID); +jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID); +jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID); +jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID); +jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID); +void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val); +void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val); +void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); +void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val); +void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val); +void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint val); +void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val); +void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val); +void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val); +jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, + const char *sig); +jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); +jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); +jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...); +jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...); +jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); +jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...); +jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...); +jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); +jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, + ...); +jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args); +jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, + const jvalue *args); +void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...); +void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, + va_list args); +void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, + const jvalue *args); +jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, + const char *sig); +jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID); +jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID); +void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jobject value); +void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jboolean value); +void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jbyte value); +void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jchar value); +void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jshort value); +void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value); +void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jlong value); +void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jfloat value); +void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, + jdouble value); +jstring NewString(JNIEnv *env, const jchar *unicode, jsize len); +jsize GetStringLength(JNIEnv *env, jstring str); +const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy); +void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars); +jstring NewStringUTF(JNIEnv *env, const char *utf); +jsize GetStringUTFLength(JNIEnv *env, jstring str); +const char *GetStringUTFChars(JNIEnv *env, jstring str, jboolean *isCopy); +void ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars); +jsize GetArrayLength(JNIEnv *env, jarray array); +jobjectArray NewObjectArray(JNIEnv *env, jsize len, jclass clazz, jobject init); +jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index); +void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, + jobject val); +jbooleanArray NewBooleanArray(JNIEnv *env, jsize len); +jbyteArray NewByteArray(JNIEnv *env, jsize len); +jcharArray NewCharArray(JNIEnv *env, jsize len); +jshortArray NewShortArray(JNIEnv *env, jsize len); +jintArray NewIntArray(JNIEnv *env, jsize len); +jlongArray NewLongArray(JNIEnv *env, jsize len); +jfloatArray NewFloatArray(JNIEnv *env, jsize len); +jdoubleArray NewDoubleArray(JNIEnv *env, jsize len); +jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *isCopy); +jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy); +jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy); +jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy); +jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy); +jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy); +jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy); +jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jboolean *isCopy); +void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *elems, jint mode); +void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, + jint mode); +void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems, + jint mode); +void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems, + jint mode); +void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems, + jint mode); +void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems, + jint mode); +void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, + jint mode); +void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array, jdouble *elems, + jint mode); +void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize l, jboolean *buf); +void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf); +void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf); +void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, + jshort *buf); +void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf); +void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, + jlong *buf); +void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, + jfloat *buf); +void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf); +void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize l, const jboolean *buf); +void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + const jbyte *buf); +void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + const jchar *buf); +void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, jsize len, + const jshort *buf); +void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + const jint *buf); +void SetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, + const jlong *buf); +void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, jsize len, + const jfloat *buf); +void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, const jdouble *buf); +jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods); +jint UnregisterNatives(JNIEnv *env, jclass clazz); +jint MonitorEnter(JNIEnv *env, jobject obj); +jint MonitorExit(JNIEnv *env, jobject obj); +jint GetJavaVM(JNIEnv *env, JavaVM **vm); +void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, + jchar *buf); +void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, + char *buf); +void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy); +void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, + jint mode); +const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy); +void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring); +jweak NewWeakGlobalRef(JNIEnv *env, jobject obj); +void DeleteWeakGlobalRef(JNIEnv *env, jweak ref); +jboolean ExceptionCheck(JNIEnv *env); +jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity); +void *GetDirectBufferAddress(JNIEnv *env, jobject buf); +jlong GetDirectBufferCapacity(JNIEnv *env, jobject buf); +jobjectRefType GetObjectRefType(JNIEnv *env, jobject obj); +jobject GetModule(JNIEnv *env, jclass clazz); +jboolean IsVirtualThread(JNIEnv *env, jobject obj); +} // namespace jvmilia diff --git a/lib/exec/jvm.ml b/lib/exec/jvm.ml new file mode 100644 index 0000000..4c2958b --- /dev/null +++ b/lib/exec/jvm.ml @@ -0,0 +1,154 @@ +open Java +module StringMap = Map.Make (String) + +type evalue = Void | Null +type exec_frame = { locals : evalue array; mutable stack : evalue list } +type eclass = { raw : jclass; mutable static : evalue StringMap.t } +type instrlink = { instr : Instr.instruction; next : instrlink option } + +let string_of_evalue (value : evalue) : string = + match value with Void -> "void" | Null -> "null" + +let find_method (cls : eclass) (name : string) (desc : string) : jmethod option + = + let matches m = m.desc = desc && m.name = name in + List.find_opt matches cls.raw.methods + +class jvm libjava interface = + object (self) + val mutable frames : exec_frame list = [] + val mutable loaded : eclass StringMap.t = StringMap.empty + val libjava : int64 = libjava + val interface : int64 = interface + method free = Shim.free_native_interface interface + method private curframe = List.hd frames + + method private push (value : evalue) = + let frame = self#curframe in + frame.stack <- value :: frame.stack + + method private pop () : evalue = + let frame = self#curframe in + let value = List.hd frame.stack in + frame.stack <- List.tl frame.stack; + value + + method private add_frame (frame_size : int) = + let locals = Array.make frame_size Void in + let stack = [] in + let new_frame = { locals; stack } in + frames <- new_frame :: frames + + method private mark_loaded (cls : eclass) = + loaded <- StringMap.add cls.raw.name cls loaded + + method private find_loaded (name : string) : eclass option = + StringMap.find_opt name loaded + + method private load_class (class_name : string) : eclass = + match self#find_loaded class_name with + | Some existing -> existing + | None -> self#perform_class_load class_name + + method private perform_class_load (class_name : string) : eclass = + let cls = Loader.load_class class_name Loader.bootstrap_loader in + let safe = Verify.Main.classIsTypeSafe cls in + if not safe then + failwith (Printf.sprintf "Class %S failed verification" class_name); + let ecls = { raw = cls; static = StringMap.empty } in + self#mark_loaded ecls; + (* mark as loaded before clinit, otherwise we recurse *) + (match find_method ecls "" "()V" with + | Some clinit -> + self#exec ecls clinit; + () + | None -> ()); + (* openjdk is special *) + (if cls.name = "java/lang/System" then + match find_method ecls "initPhase1" "()V" with + | Some init -> + self#exec ecls init; + () + | None -> ()); + (* todo other verification/linking stuff idk *) + ecls + + method private exec_instr (_cls : eclass) (_mth : jmethod) + (_code : Attr.code_attribute) (instr : Instr.instruction) : unit = + let _i, body = instr in + match body with + | Invokestatic method_desc -> + let def_cls = self#load_class method_desc.cls in + let def_mth = + match find_method def_cls method_desc.name method_desc.desc with + | Some m -> m + | None -> + failwith + "Cannot find method to invokestatic (TODO add more info)" + in + assert ( + def_mth.access_flags.is_static + && not def_mth.access_flags.is_abstract); + (* todo frame stuff *) + self#exec def_cls def_mth + | Getstatic field_desc -> + let def_cls = self#load_class field_desc.cls in + failwith (Printf.sprintf "getstatic %s" def_cls.raw.name) + | Putstatic field_desc -> + let def_cls = self#load_class field_desc.cls in + let value = self#pop () in + def_cls.static <- StringMap.add field_desc.name value def_cls.static; + Printf.printf "putstatic %s %s %s %s\n" def_cls.raw.name + field_desc.name field_desc.desc (string_of_evalue value) + | Aconst_null -> self#push Null + | x -> + failwith + (Printf.sprintf "Unimplemented instruction excecution %s" + (Instr.string_of_instr x)) + + method private exec_code (cls : eclass) (mth : jmethod) + (code : Attr.code_attribute) : unit = + Debug.push "jvm_exec_code" + (Printf.sprintf "%s.%s %s" cls.raw.name mth.name mth.desc); + self#add_frame code.frame_size; + List.iter (self#exec_instr cls mth code) code.code; + Debug.pop () + + method private exec (cls : eclass) (mth : jmethod) : unit = + let find_code (attr : Attr.attribute) : Attr.code_attribute option = + match attr with Code x -> Some x | _ -> None + in + if mth.access_flags.is_native then ( + let as_underscore c = if c = '/' then '_' else c in + let native_name = + "Java_" ^ String.map as_underscore cls.raw.name ^ "_" ^ mth.name + in + Printf.printf "Native method %s.%s -> %s\n" cls.raw.name mth.name + native_name; + let method_handle = Shim.load_method libjava native_name in + Printf.printf "%s -> %#Lx\n%!" native_name method_handle; + Shim.execute_native_noargs_void interface cls.raw.name method_handle) + else + match List.find_map find_code mth.attributes with + | Some code_attr -> self#exec_code cls mth code_attr + | None -> failwith "Can't execute non-code method" + + method exec_main (main_class_name : string) : unit = + let main_class = self#load_class main_class_name in + match find_method main_class "main" "([Ljava/lang/String;)V" with + | Some main_method -> + let flags = main_method.access_flags in + if not flags.is_static then failwith "Main method is not static"; + if not flags.is_public then failwith "Main method is not public"; + self#exec main_class main_method + | None -> failwith "This class does not have a main method" + end + +let create_jvm (loader : string -> jclass) : jvm = + (* TODO: maybe this should be stored in jvm *) + Loader.initialize_bootstrap_loader loader; + let libjvm = Shim.load_library "/usr/lib/jvm/default/lib/server/libjvm.so" in + let libjava = Shim.load_library "./class/extern-lib/libjava.so" in + let interface = Shim.make_native_interface () in + Printf.printf "libjvm: %#Lx, libjava: %#Lx\n" libjvm libjava; + new jvm libjava interface diff --git a/lib/exec/native.cpp b/lib/exec/native.cpp new file mode 100644 index 0000000..5865488 --- /dev/null +++ b/lib/exec/native.cpp @@ -0,0 +1,370 @@ +#include "native.h" +#include "jni.h" +#include +#include +#include +#include +#include +#include +#include + +using jvmilia::JVMData, jvmilia::Context; + +value handle_to_value(void *handle) { + return caml_copy_int64(std::bit_cast(handle)); +} + +template T *value_to_handle(value val) { + return std::bit_cast(Int64_val(val)); +} + +int fib(int n) { + if (n < 2) + return 1; + else + return fib(n - 1) + fib(n - 2); +} + +CAMLprim value fib_native(value n) { return Val_int(fib(Int_val(n))); } + +CAMLprim value load_library_native(value path) { + const char *path_str = String_val(path); + char *current_path = get_current_dir_name(); + printf("We are in: %s\n", current_path); + free(current_path); + printf("Loading library: %s\n", path_str); + void *library = dlopen(path_str, RTLD_LAZY | RTLD_GLOBAL); + printf("Library: %p\n", library); + // link_map *map = nullptr; + // dlinfo(library, RTLD_DI_LINKMAP, &map); + + // Elf64_Sym *symtab = nullptr; + // char *strtab = nullptr; + // int symentries = 0; + // for (auto section = map->l_ld; section->d_tag != DT_NULL; ++section) { + // if (section->d_tag == DT_SYMTAB) { + // symtab = (Elf64_Sym *)section->d_un.d_ptr; + // } + // if (section->d_tag == DT_STRTAB) { + // strtab = (char *)section->d_un.d_ptr; + // } + // if (section->d_tag == DT_SYMENT) { + // symentries = section->d_un.d_val; + // } + // } + // int size = strtab - (char *)symtab; + // for (int k = 0; k < size / symentries; ++k) { + // auto sym = &symtab[k]; + // // If sym is function + // if (ELF64_ST_TYPE(symtab[k].st_info) == STT_FUNC) { + // // str is name of each symbol + // auto str = &strtab[sym->st_name]; + // printf("%s\n", str); + // } + // } + + // dlclose(library); + + return handle_to_value(library); +} + +CAMLprim value load_method_native(value lib_val, value name_val) { + void *lib = value_to_handle(lib_val); + const char *name = String_val(name_val); + + void *method = dlsym(lib, name); + + return handle_to_value(method); +} + +CAMLprim value make_native_interface_native(value unit) { + (void)unit; + + JNINativeInterface *interface = new JNINativeInterface; + *interface = { + nullptr, + nullptr, + nullptr, + nullptr, + + /* GetVersion= */ &jvmilia::GetVersion, + /* DefineClass= */ &jvmilia::DefineClass, + /* FindClass= */ &jvmilia::FindClass, + /* FromReflectedMethod= */ &jvmilia::FromReflectedMethod, + /* FromReflectedField= */ &jvmilia::FromReflectedField, + /* ToReflectedMethod= */ &jvmilia::ToReflectedMethod, + /* GetSuperclass= */ &jvmilia::GetSuperclass, + /* IsAssignableFrom= */ &jvmilia::IsAssignableFrom, + /* ToReflectedField= */ &jvmilia::ToReflectedField, + /* Throw= */ &jvmilia::Throw, + /* ThrowNew= */ &jvmilia::ThrowNew, + /* ExceptionOccurred= */ &jvmilia::ExceptionOccurred, + /* ExceptionDescribe= */ &jvmilia::ExceptionDescribe, + /* ExceptionClear= */ &jvmilia::ExceptionClear, + /* FatalError= */ &jvmilia::FatalError, + /* PushLocalFrame= */ &jvmilia::PushLocalFrame, + /* PopLocalFrame= */ &jvmilia::PopLocalFrame, + /* NewGlobalRef= */ &jvmilia::NewGlobalRef, + /* DeleteGlobalRef= */ &jvmilia::DeleteGlobalRef, + /* DeleteLocalRef= */ &jvmilia::DeleteLocalRef, + /* IsSameObject= */ &jvmilia::IsSameObject, + /* NewLocalRef= */ &jvmilia::NewLocalRef, + /* EnsureLocalCapacity= */ &jvmilia::EnsureLocalCapacity, + /* AllocObject= */ &jvmilia::AllocObject, + /* NewObject= */ &jvmilia::NewObject, + /* NewObjectV= */ &jvmilia::NewObjectV, + /* NewObjectA= */ &jvmilia::NewObjectA, + /* GetObjectClass= */ &jvmilia::GetObjectClass, + /* IsInstanceOf= */ &jvmilia::IsInstanceOf, + /* GetMethodID= */ &jvmilia::GetMethodID, + /* CallObjectMethod= */ &jvmilia::CallObjectMethod, + /* CallObjectMethodV= */ &jvmilia::CallObjectMethodV, + /* CallObjectMethodA= */ &jvmilia::CallObjectMethodA, + /* CallBooleanMethod= */ &jvmilia::CallBooleanMethod, + /* CallBooleanMethodV= */ &jvmilia::CallBooleanMethodV, + /* CallBooleanMethodA= */ &jvmilia::CallBooleanMethodA, + /* CallByteMethod= */ &jvmilia::CallByteMethod, + /* CallByteMethodV= */ &jvmilia::CallByteMethodV, + /* CallByteMethodA= */ &jvmilia::CallByteMethodA, + /* CallCharMethod= */ &jvmilia::CallCharMethod, + /* CallCharMethodV= */ &jvmilia::CallCharMethodV, + /* CallCharMethodA= */ &jvmilia::CallCharMethodA, + /* CallShortMethod= */ &jvmilia::CallShortMethod, + /* CallShortMethodV= */ &jvmilia::CallShortMethodV, + /* CallShortMethodA= */ &jvmilia::CallShortMethodA, + /* CallIntMethod= */ &jvmilia::CallIntMethod, + /* CallIntMethodV= */ &jvmilia::CallIntMethodV, + /* CallIntMethodA= */ &jvmilia::CallIntMethodA, + /* CallLongMethod= */ &jvmilia::CallLongMethod, + /* CallLongMethodV= */ &jvmilia::CallLongMethodV, + /* CallLongMethodA= */ &jvmilia::CallLongMethodA, + /* CallFloatMethod= */ &jvmilia::CallFloatMethod, + /* CallFloatMethodV= */ &jvmilia::CallFloatMethodV, + /* CallFloatMethodA= */ &jvmilia::CallFloatMethodA, + /* CallDoubleMethod= */ &jvmilia::CallDoubleMethod, + /* CallDoubleMethodV= */ &jvmilia::CallDoubleMethodV, + /* CallDoubleMethodA= */ &jvmilia::CallDoubleMethodA, + /* CallVoidMethod= */ &jvmilia::CallVoidMethod, + /* CallVoidMethodV= */ &jvmilia::CallVoidMethodV, + /* CallVoidMethodA= */ &jvmilia::CallVoidMethodA, + /* CallNonvirtualObjectMethod= */ + &jvmilia::CallNonvirtualObjectMethod, + /* CallNonvirtualObjectMethodV= */ + &jvmilia::CallNonvirtualObjectMethodV, + /* CallNonvirtualObjectMethodA= */ + &jvmilia::CallNonvirtualObjectMethodA, + /* CallNonvirtualBooleanMethod= */ + &jvmilia::CallNonvirtualBooleanMethod, + /* CallNonvirtualBooleanMethodV= */ + &jvmilia::CallNonvirtualBooleanMethodV, + /* CallNonvirtualBooleanMethodA= */ + &jvmilia::CallNonvirtualBooleanMethodA, + /* CallNonvirtualByteMethod= */ &jvmilia::CallNonvirtualByteMethod, + /* CallNonvirtualByteMethodV= */ &jvmilia::CallNonvirtualByteMethodV, + /* CallNonvirtualByteMethodA= */ &jvmilia::CallNonvirtualByteMethodA, + /* CallNonvirtualCharMethod= */ &jvmilia::CallNonvirtualCharMethod, + /* CallNonvirtualCharMethodV= */ &jvmilia::CallNonvirtualCharMethodV, + /* CallNonvirtualCharMethodA= */ &jvmilia::CallNonvirtualCharMethodA, + /* CallNonvirtualShortMethod= */ &jvmilia::CallNonvirtualShortMethod, + /* CallNonvirtualShortMethodV= */ + &jvmilia::CallNonvirtualShortMethodV, + /* CallNonvirtualShortMethodA= */ + &jvmilia::CallNonvirtualShortMethodA, + /* CallNonvirtualIntMethod= */ &jvmilia::CallNonvirtualIntMethod, + /* CallNonvirtualIntMethodV= */ &jvmilia::CallNonvirtualIntMethodV, + /* CallNonvirtualIntMethodA= */ &jvmilia::CallNonvirtualIntMethodA, + /* CallNonvirtualLongMethod= */ &jvmilia::CallNonvirtualLongMethod, + /* CallNonvirtualLongMethodV= */ &jvmilia::CallNonvirtualLongMethodV, + /* CallNonvirtualLongMethodA= */ &jvmilia::CallNonvirtualLongMethodA, + /* CallNonvirtualFloatMethod= */ &jvmilia::CallNonvirtualFloatMethod, + /* CallNonvirtualFloatMethodV= */ + &jvmilia::CallNonvirtualFloatMethodV, + /* CallNonvirtualFloatMethodA= */ + &jvmilia::CallNonvirtualFloatMethodA, + /* CallNonvirtualDoubleMethod= */ + &jvmilia::CallNonvirtualDoubleMethod, + /* CallNonvirtualDoubleMethodV= */ + &jvmilia::CallNonvirtualDoubleMethodV, + /* CallNonvirtualDoubleMethodA= */ + &jvmilia::CallNonvirtualDoubleMethodA, + /* CallNonvirtualVoidMethod= */ &jvmilia::CallNonvirtualVoidMethod, + /* CallNonvirtualVoidMethodV= */ &jvmilia::CallNonvirtualVoidMethodV, + /* CallNonvirtualVoidMethodA= */ &jvmilia::CallNonvirtualVoidMethodA, + /* GetFieldID= */ &jvmilia::GetFieldID, + /* GetObjectField= */ &jvmilia::GetObjectField, + /* GetBooleanField= */ &jvmilia::GetBooleanField, + /* GetByteField= */ &jvmilia::GetByteField, + /* GetCharField= */ &jvmilia::GetCharField, + /* GetShortField= */ &jvmilia::GetShortField, + /* GetIntField= */ &jvmilia::GetIntField, + /* GetLongField= */ &jvmilia::GetLongField, + /* GetFloatField= */ &jvmilia::GetFloatField, + /* GetDoubleField= */ &jvmilia::GetDoubleField, + /* SetObjectField= */ &jvmilia::SetObjectField, + /* SetBooleanField= */ &jvmilia::SetBooleanField, + /* SetByteField= */ &jvmilia::SetByteField, + /* SetCharField= */ &jvmilia::SetCharField, + /* SetShortField= */ &jvmilia::SetShortField, + /* SetIntField= */ &jvmilia::SetIntField, + /* SetLongField= */ &jvmilia::SetLongField, + /* SetFloatField= */ &jvmilia::SetFloatField, + /* SetDoubleField= */ &jvmilia::SetDoubleField, + /* GetStaticMethodID= */ &jvmilia::GetStaticMethodID, + /* CallStaticObjectMethod= */ &jvmilia::CallStaticObjectMethod, + /* CallStaticObjectMethodV= */ &jvmilia::CallStaticObjectMethodV, + /* CallStaticObjectMethodA= */ &jvmilia::CallStaticObjectMethodA, + /* CallStaticBooleanMethod= */ &jvmilia::CallStaticBooleanMethod, + /* CallStaticBooleanMethodV= */ &jvmilia::CallStaticBooleanMethodV, + /* CallStaticBooleanMethodA= */ &jvmilia::CallStaticBooleanMethodA, + /* CallStaticByteMethod= */ &jvmilia::CallStaticByteMethod, + /* CallStaticByteMethodV= */ &jvmilia::CallStaticByteMethodV, + /* CallStaticByteMethodA= */ &jvmilia::CallStaticByteMethodA, + /* CallStaticCharMethod= */ &jvmilia::CallStaticCharMethod, + /* CallStaticCharMethodV= */ &jvmilia::CallStaticCharMethodV, + /* CallStaticCharMethodA= */ &jvmilia::CallStaticCharMethodA, + /* CallStaticShortMethod= */ &jvmilia::CallStaticShortMethod, + /* CallStaticShortMethodV= */ &jvmilia::CallStaticShortMethodV, + /* CallStaticShortMethodA= */ &jvmilia::CallStaticShortMethodA, + /* CallStaticIntMethod= */ &jvmilia::CallStaticIntMethod, + /* CallStaticIntMethodV= */ &jvmilia::CallStaticIntMethodV, + /* CallStaticIntMethodA= */ &jvmilia::CallStaticIntMethodA, + /* CallStaticLongMethod= */ &jvmilia::CallStaticLongMethod, + /* CallStaticLongMethodV= */ &jvmilia::CallStaticLongMethodV, + /* CallStaticLongMethodA= */ &jvmilia::CallStaticLongMethodA, + /* CallStaticFloatMethod= */ &jvmilia::CallStaticFloatMethod, + /* CallStaticFloatMethodV= */ &jvmilia::CallStaticFloatMethodV, + /* CallStaticFloatMethodA= */ &jvmilia::CallStaticFloatMethodA, + /* CallStaticDoubleMethod= */ &jvmilia::CallStaticDoubleMethod, + /* CallStaticDoubleMethodV= */ &jvmilia::CallStaticDoubleMethodV, + /* CallStaticDoubleMethodA= */ &jvmilia::CallStaticDoubleMethodA, + /* CallStaticVoidMethod= */ &jvmilia::CallStaticVoidMethod, + /* CallStaticVoidMethodV= */ &jvmilia::CallStaticVoidMethodV, + /* CallStaticVoidMethodA= */ &jvmilia::CallStaticVoidMethodA, + /* GetStaticFieldID= */ &jvmilia::GetStaticFieldID, + /* GetStaticObjectField= */ &jvmilia::GetStaticObjectField, + /* GetStaticBooleanField= */ &jvmilia::GetStaticBooleanField, + /* GetStaticByteField= */ &jvmilia::GetStaticByteField, + /* GetStaticCharField= */ &jvmilia::GetStaticCharField, + /* GetStaticShortField= */ &jvmilia::GetStaticShortField, + /* GetStaticIntField= */ &jvmilia::GetStaticIntField, + /* GetStaticLongField= */ &jvmilia::GetStaticLongField, + /* GetStaticFloatField= */ &jvmilia::GetStaticFloatField, + /* GetStaticDoubleField= */ &jvmilia::GetStaticDoubleField, + /* SetStaticObjectField= */ &jvmilia::SetStaticObjectField, + /* SetStaticBooleanField= */ &jvmilia::SetStaticBooleanField, + /* SetStaticByteField= */ &jvmilia::SetStaticByteField, + /* SetStaticCharField= */ &jvmilia::SetStaticCharField, + /* SetStaticShortField= */ &jvmilia::SetStaticShortField, + /* SetStaticIntField= */ &jvmilia::SetStaticIntField, + /* SetStaticLongField= */ &jvmilia::SetStaticLongField, + /* SetStaticFloatField= */ &jvmilia::SetStaticFloatField, + /* SetStaticDoubleField= */ &jvmilia::SetStaticDoubleField, + /* NewString= */ &jvmilia::NewString, + /* GetStringLength= */ &jvmilia::GetStringLength, + /* GetStringChars= */ &jvmilia::GetStringChars, + /* ReleaseStringChars= */ &jvmilia::ReleaseStringChars, + /* NewStringUTF= */ &jvmilia::NewStringUTF, + /* GetStringUTFLength= */ &jvmilia::GetStringUTFLength, + /* GetStringUTFChars= */ &jvmilia::GetStringUTFChars, + /* ReleaseStringUTFChars= */ &jvmilia::ReleaseStringUTFChars, + /* GetArrayLength= */ &jvmilia::GetArrayLength, + /* NewObjectArray= */ &jvmilia::NewObjectArray, + /* GetObjectArrayElement= */ &jvmilia::GetObjectArrayElement, + /* SetObjectArrayElement= */ &jvmilia::SetObjectArrayElement, + /* NewBooleanArray= */ &jvmilia::NewBooleanArray, + /* NewByteArray= */ &jvmilia::NewByteArray, + /* NewCharArray= */ &jvmilia::NewCharArray, + /* NewShortArray= */ &jvmilia::NewShortArray, + /* NewIntArray= */ &jvmilia::NewIntArray, + /* NewLongArray= */ &jvmilia::NewLongArray, + /* NewFloatArray= */ &jvmilia::NewFloatArray, + /* NewDoubleArray= */ &jvmilia::NewDoubleArray, + /* GetBooleanArrayElements= */ &jvmilia::GetBooleanArrayElements, + /* GetByteArrayElements= */ &jvmilia::GetByteArrayElements, + /* GetCharArrayElements= */ &jvmilia::GetCharArrayElements, + /* GetShortArrayElements= */ &jvmilia::GetShortArrayElements, + /* GetIntArrayElements= */ &jvmilia::GetIntArrayElements, + /* GetLongArrayElements= */ &jvmilia::GetLongArrayElements, + /* GetFloatArrayElements= */ &jvmilia::GetFloatArrayElements, + /* GetDoubleArrayElements= */ &jvmilia::GetDoubleArrayElements, + /* ReleaseBooleanArrayElements= */ + &jvmilia::ReleaseBooleanArrayElements, + /* ReleaseByteArrayElements= */ &jvmilia::ReleaseByteArrayElements, + /* ReleaseCharArrayElements= */ &jvmilia::ReleaseCharArrayElements, + /* ReleaseShortArrayElements= */ &jvmilia::ReleaseShortArrayElements, + /* ReleaseIntArrayElements= */ &jvmilia::ReleaseIntArrayElements, + /* ReleaseLongArrayElements= */ &jvmilia::ReleaseLongArrayElements, + /* ReleaseFloatArrayElements= */ &jvmilia::ReleaseFloatArrayElements, + /* ReleaseDoubleArrayElements= */ + &jvmilia::ReleaseDoubleArrayElements, + /* GetBooleanArrayRegion= */ &jvmilia::GetBooleanArrayRegion, + /* GetByteArrayRegion= */ &jvmilia::GetByteArrayRegion, + /* GetCharArrayRegion= */ &jvmilia::GetCharArrayRegion, + /* GetShortArrayRegion= */ &jvmilia::GetShortArrayRegion, + /* GetIntArrayRegion= */ &jvmilia::GetIntArrayRegion, + /* GetLongArrayRegion= */ &jvmilia::GetLongArrayRegion, + /* GetFloatArrayRegion= */ &jvmilia::GetFloatArrayRegion, + /* GetDoubleArrayRegion= */ &jvmilia::GetDoubleArrayRegion, + /* SetBooleanArrayRegion= */ &jvmilia::SetBooleanArrayRegion, + /* SetByteArrayRegion= */ &jvmilia::SetByteArrayRegion, + /* SetCharArrayRegion= */ &jvmilia::SetCharArrayRegion, + /* SetShortArrayRegion= */ &jvmilia::SetShortArrayRegion, + /* SetIntArrayRegion= */ &jvmilia::SetIntArrayRegion, + /* SetLongArrayRegion= */ &jvmilia::SetLongArrayRegion, + /* SetFloatArrayRegion= */ &jvmilia::SetFloatArrayRegion, + /* SetDoubleArrayRegion= */ &jvmilia::SetDoubleArrayRegion, + /* RegisterNatives= */ &jvmilia::RegisterNatives, + /* UnregisterNatives= */ &jvmilia::UnregisterNatives, + /* MonitorEnter= */ &jvmilia::MonitorEnter, + /* MonitorExit= */ &jvmilia::MonitorExit, + /* GetJavaVM= */ &jvmilia::GetJavaVM, + /* GetStringRegion= */ &jvmilia::GetStringRegion, + /* GetStringUTFRegion= */ &jvmilia::GetStringUTFRegion, + /* GetPrimitiveArrayCritical= */ &jvmilia::GetPrimitiveArrayCritical, + /* ReleasePrimitiveArrayCritical= */ + &jvmilia::ReleasePrimitiveArrayCritical, + /* GetStringCritical= */ &jvmilia::GetStringCritical, + /* ReleaseStringCritical= */ &jvmilia::ReleaseStringCritical, + /* NewWeakGlobalRef= */ &jvmilia::NewWeakGlobalRef, + /* DeleteWeakGlobalRef= */ &jvmilia::DeleteWeakGlobalRef, + /* ExceptionCheck= */ &jvmilia::ExceptionCheck, + /* NewDirectByteBuffer= */ &jvmilia::NewDirectByteBuffer, + /* GetDirectBufferAddress= */ &jvmilia::GetDirectBufferAddress, + /* GetDirectBufferCapacity= */ &jvmilia::GetDirectBufferCapacity, + /* GetObjectRefType= */ &jvmilia::GetObjectRefType, + /* GetModule= */ &jvmilia::GetModule, + /* IsVirtualThread= */ &jvmilia::IsVirtualThread, + }; + JVMData *data = new JVMData; + + Context *context = new Context; + context->interface = interface; + context->data = data; + + // __builtin_dump_struct(context, printf); + printf("interface: %p; data: %p; context: %p\n", interface, data, context); + + return handle_to_value(context); +} + +CAMLprim value free_native_interface_native(value handle) { + auto *context = value_to_handle(handle); + + delete context; + + return Val_unit; +} + +using noargs_void = void(JNIEnv *, jclass); +CAMLprim value execute_native_noargs_void_native(value interface_int, + value cls_value, + value fn_int) { + auto context = value_to_handle(interface_int); + auto cls_string = String_val(cls_value); + auto cls = std::bit_cast(cls_string); + auto function = value_to_handle(fn_int); + + function(&context->interface, cls); + + return Val_unit; +} diff --git a/lib/exec/native.h b/lib/exec/native.h new file mode 100644 index 0000000..c7f1262 --- /dev/null +++ b/lib/exec/native.h @@ -0,0 +1,27 @@ +#pragma once +#include + +extern "C" { + +// external fib : int -> int = "fib_native" +CAMLprim value fib_native(value n); + +// external load_library : string -> int64 = "load_library_native" +CAMLprim value load_library_native(value name); + +// external load_method : int64 -> string -> int64 = "load_method_native" +CAMLprim value load_method_native(value library, value name); + +// external make_native_interface : unit -> int64 = +// "make_native_interface_native" +CAMLprim value make_native_interface_native(value unit); + +// external free_native_interface : int64 -> unit = +// "free_native_interface_native" +CAMLprim value free_native_interface_native(value handle); + +// external execute_native_noargs_void : int64 -> string -> int64 -> unit = +// "execute_native_noargs_void_native" +CAMLprim value execute_native_noargs_void_native(value interface, value cls, + value handle); +} diff --git a/lib/exec/shim.ml b/lib/exec/shim.ml new file mode 100644 index 0000000..484498c --- /dev/null +++ b/lib/exec/shim.ml @@ -0,0 +1,8 @@ +external fib : int -> int = "fib_native" +external load_library : string -> int64 = "load_library_native" +external load_method : int64 -> string -> int64 = "load_method_native" +external make_native_interface : unit -> int64 = "make_native_interface_native" +external free_native_interface : int64 -> unit = "free_native_interface_native" + +external execute_native_noargs_void : int64 -> string -> int64 -> unit + = "execute_native_noargs_void_native" diff --git a/lib/loader.ml b/lib/loader.ml index 34c740f..5c892dc 100644 --- a/lib/loader.ml +++ b/lib/loader.ml @@ -1,10 +1,9 @@ open Java open Shared - module StringMap = Map.Make (String) type bootstrap_loader = { - known : jclass StringMap.t ref; + mutable known : jclass StringMap.t; load : string -> jclass; } @@ -15,7 +14,7 @@ let initialize_bootstrap_loader (loader : string -> jclass) : unit = | Some _ -> failwith "Bootstrap loader has already been initialized" | None -> bootstrap_loader_ref := - Some { known = ref StringMap.empty; load = loader } + Some { known = StringMap.empty; load = loader } let bootstrap_loader_impl () : bootstrap_loader = match !bootstrap_loader_ref with @@ -23,3 +22,16 @@ let bootstrap_loader_impl () : bootstrap_loader = | None -> failwith "Bootstrap loader has not been initialized" let bootstrap_loader = Bootstrap + +let load_class (name : string) (loader : jloader) : jclass = + match loader with + | Bootstrap -> ( + let impl = bootstrap_loader_impl () in + match StringMap.find_opt name impl.known with + | Some existing -> existing + | None -> + let cls = impl.load name in + impl.known <- StringMap.add name cls impl.known; + cls) + | UserDefined n -> + failwith (Printf.sprintf "Cannot use user-defined loader %s" n) diff --git a/lib/verify/main.ml b/lib/verify/main.ml index 813cbad..993392a 100644 --- a/lib/verify/main.ml +++ b/lib/verify/main.ml @@ -29,25 +29,11 @@ let method_matches_desc (d : method_desc) (m : jmethod) : bool = let member_method_opt (desc : method_desc) (cls : jclass) : jmethod option = List.find_opt (method_matches_desc desc) cls.methods -(* loadedClass(Name, InitiatingLoader, ClassDefinition) *) -let load_class (name : string) (loader : jloader) : jclass = - match loader with - | Bootstrap -> ( - let impl = Loader.bootstrap_loader_impl () in - match Loader.StringMap.find_opt name !(impl.known) with - | Some existing -> existing - | None -> - let cls = impl.load name in - impl.known := Loader.StringMap.add name cls !(impl.known); - cls) - | UserDefined n -> - failwith (Printf.sprintf "Cannot use user-defined loader %s" n) - let thisClass (env : jenvironment) : vclass = (env.cls.name, env.cls.loader) let currentClassLoader (env : jenvironment) : jloader = env.cls.loader let rec superclassChain (name : string) (loader : jloader) : vclass list = - let cls = load_class name loader in + let cls = Loader.load_class name loader in match cls.name with | "java/lang/Object" -> assert (isBootstrapLoader cls.loader); @@ -64,8 +50,8 @@ let isJavaSubclassOf (sub : string) (sub_l : jloader) (super : string) let res = List.find_opt (fun (x, _) -> x = super) chain in match res with | Some (_, c_l) -> - let a = load_class super c_l in - let b = load_class super super_l in + let a = Loader.load_class super c_l in + let b = Loader.load_class super super_l in assert (a = b); true | None -> false @@ -78,7 +64,7 @@ let rec isJavaAssignable (a : vtype) (b : vtype) : bool = | x, y when x = y -> true | Class (_, _), Class ("java/lang/Object", Bootstrap) -> true | Class (f, fl), Class (t, tl) -> - let tc = load_class t tl in + let tc = Loader.load_class t tl in if classIsInterface tc then true else isJavaSubclassOf f fl t tl | Array _, Class (name, loader) when loader = Loader.bootstrap_loader && List.mem name array_supertypes -> @@ -140,12 +126,12 @@ and doesNotOverrideFinalMethodOfSuperclass (cls : jclass) (mth : jmethod) : bool if cls.name = "java/lang/Object" then Debug.pop true else let superclass_name = classSuperClassName cls in - let superclass = load_class superclass_name cls.loader in + let superclass = Loader.load_class superclass_name cls.loader in let result = finalMethodNotOverridden mth superclass in Debug.pop result let doesNotOverrideFinalMethod (cls : jclass) (mth : jmethod) : bool = - Debug.push "doesNotOverrideFinalMethod" (Debug.method_diagnostic mth cls); + (* Debug.push "doesNotOverrideFinalMethod" (Debug.method_diagnostic mth cls); *) let result = (cls.name = "java/lang/Object" && isBootstrapLoader cls.loader) || mth.access_flags.is_private || mth.access_flags.is_static @@ -153,7 +139,8 @@ let doesNotOverrideFinalMethod (cls : jclass) (mth : jmethod) : bool = && (not mth.access_flags.is_static) && doesNotOverrideFinalMethodOfSuperclass cls mth in - Debug.pop result + (* Debug.pop result *) + result let rec mergeStackMapAndCode (stack_map : jstack_map list) (code : Instr.instruction list) : merged_code list = @@ -844,13 +831,11 @@ let expand_locals (frame_size : int) (locals : vtype list) : vtype list = let convert_stack_map (frame_size : int) ((offset, frame) : jstack_map) ((delta, desc) : delta_frame) : jstack_map * jstack_map = - let () = - if offset = 0 then Printf.printf " 0: %s\n" (string_of_frame frame) - else () - in + if offset = 0 && not Debug.concise then + Printf.printf " 0: %s\n" (string_of_frame frame); let this_offset = offset + delta in let next_offset = this_offset + 1 in - let () = + if not Debug.concise then Printf.printf "%4d: %s\n" this_offset (match desc with | Same -> "same" @@ -863,8 +848,7 @@ let convert_stack_map (frame_size : int) ((offset, frame) : jstack_map) | FullFrame i -> Printf.sprintf "full_frame locals=[%s] stack=[%s]" (List.map string_of_vtype i.locals |> String.concat ", ") - (List.map string_of_vtype i.stack |> String.concat ", ")) - in + (List.map string_of_vtype i.stack |> String.concat ", ")); let v = match desc with | Same -> { frame with stack = [] } @@ -881,7 +865,8 @@ let convert_stack_map (frame_size : int) ((offset, frame) : jstack_map) in let has_uninit = List.mem UninitializedThis v.locals in let v_with_uninit = { v with flags = { is_this_uninit = has_uninit } } in - let () = Printf.printf " %s\n" (string_of_frame v_with_uninit) in + if not Debug.concise then + Printf.printf " %s\n" (string_of_frame v_with_uninit); ((next_offset, v_with_uninit), (this_offset, v_with_uninit)) let get_stack_map (code : code_attribute) : delta_frame list = @@ -893,7 +878,7 @@ let get_stack_map (code : code_attribute) : delta_frame list = match v with Some x -> x | None -> [] let methodWithCodeIsTypeSafe (cls : jclass) (mth : jmethod) : bool = - Debug.push "methodWithCodeIsTypeSafe" (Debug.method_diagnostic mth cls); + (* Debug.push "methodWithCodeIsTypeSafe" (Debug.method_diagnostic mth cls); *) let find_code (attr : attribute) : code_attribute option = match attr with Code x -> Some x | _ -> None in @@ -929,7 +914,8 @@ let methodWithCodeIsTypeSafe (cls : jclass) (mth : jmethod) : bool = assert (handlersAreLegal env); let result = mergedCodeIsTypeSafe env merged (Frame stack_frame) in - Debug.pop result + (* Debug.pop result *) + result | None -> failwith (Printf.sprintf "Method %s is missing Code attribute" @@ -962,7 +948,7 @@ let classIsTypeSafe (cls : jclass) : bool = let super_chain = superclassChain cls.name cls.loader in let () = assert (not (List.is_empty super_chain)) in let superclass_name = classSuperClassName cls in - let superclass = load_class superclass_name cls.loader in + let superclass = Loader.load_class superclass_name cls.loader in let () = if classIsNotFinal superclass then () else diff --git a/lib/verify/main.mli b/lib/verify/main.mli index 505147a..6798e18 100644 --- a/lib/verify/main.mli +++ b/lib/verify/main.mli @@ -1,2 +1 @@ -val load_class : string -> Shared.jloader -> Java.jclass val classIsTypeSafe : Java.jclass -> bool