📄 jni.c
字号:
/* * jni.c * Java Native Interface. * * Copyright (c) 1996, 1997 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include "config-std.h"#include "config-mem.h"#include "jni.h"#include "jnirefs.h"#include "classMethod.h"#include "soft.h"#include "support.h"#include "itypes.h"#include "object.h"#include "errors.h"#include "native.h"#include "file.h"#include "baseClasses.h"#include "stringSupport.h"#include "readClass.h"#include "access.h"#include "lookup.h"#include "thread.h"#include "external.h"#include "gc.h"#include "locks.h"#include "md.h"#include "exception.h"#if defined(TRANSLATOR)#include "constpool.h"#include "seq.h"#include "slots.h"#include "registers.h"#include "labels.h"#include "codeproto.h"#include "basecode.h"#include "icode.h"#include "machine.h"#include "feedback.h"#endif#include "jvmpi_kaffe.h"/* * Define the version of JNI we support. */static int java_major_version = 1;static int java_minor_version = 1;/* * Keep track of how many VM's are active. Right now * we only support one at a time. */static int Kaffe_NumVM = 0;/* * If we must manage the JNI references for the native layer then we * add extra functions to the JNI calls and returns to manage the * referencing. */#if defined(NEED_JNIREFS)static void addJNIref(jref);static void removeJNIref(jref);#define ADD_REF(O) addJNIref(O)#define REMOVE_REF(O) removeJNIref(O)#else#define ADD_REF(O)#define REMOVE_REF(O)#endif/* * Find the function to be called when meth is invoked on obj */static inline void*getMethodFunc (Method* meth, Hjava_lang_Object *obj){ if (obj && CLASS_IS_INTERFACE (meth->class)) { register short *implementors; register Hjava_lang_Class *clazz; assert (meth->idx >= 0); implementors = meth->class->implementors; clazz = OBJECT_CLASS(obj); assert (implementors != NULL && clazz->impl_index <= implementors[0]); return clazz->itable2dtable[implementors[clazz->impl_index] + meth->idx + 1]; } else { return meth->idx >= 0 ? obj->dtable->method[meth->idx] : METHOD_INDIRECTMETHOD (meth); }}/* * Define how to set the frame pointer in a VmExceptHandler. */#if defined(TRANSLATOR)#define KAFFE_JNI_SETEXCEPTFP(ebufp) { \ vmExcept_setJNIFrame(ebufp,(uintp)__builtin_frame_address(0));\ }#else/* * Stack frame info isn't needed (and isn't available) in the * interpreter (see dispatchException/unwindStackFrame in exception.c) * However, we have to at least tag the VmExceptHandler as * a JNIFrame so the stack trace code can ignore it. */#define KAFFE_JNI_SETEXCEPTFP(ebufp) { \ vmExcept_setJNIFrame(ebufp, (uintp)ebufp); \ }#endif /* * Define how we handle exceptions in JNI. * * Each BEGIN_EXCEPTION_HANDLING macro must be matched by an * END_EXCEPTION_HANDLING macro call in the same scope. Each should * be used only once in a given JNI entrypoint. */#define BEGIN_EXCEPTION_HANDLING(X) \ VmExceptHandler ebuf; \ threadData *thread_data = THREAD_DATA(); \ KAFFE_JNI_SETEXCEPTFP(&ebuf); \ ebuf.prev = thread_data->exceptPtr;\ if (JTHREAD_SETJMP(ebuf.jbuf) != 0) { \ thread_data->exceptPtr = ebuf.prev; \ return X; \ } \ thread_data->exceptPtr = &ebuf#define BEGIN_EXCEPTION_HANDLING_VOID() \ VmExceptHandler ebuf; \ threadData *thread_data = THREAD_DATA(); \ KAFFE_JNI_SETEXCEPTFP(&ebuf); \ ebuf.prev = thread_data->exceptPtr; \ if (JTHREAD_SETJMP(ebuf.jbuf) != 0) { \ thread_data->exceptPtr = ebuf.prev; \ return; \ } \ thread_data->exceptPtr = &ebuf#define END_EXCEPTION_HANDLING() \ thread_data->exceptPtr = ebuf.prev/* * Get and set fields. */#define GET_FIELD(T,O,F) *(T*)((char*)(O) + FIELD_BOFFSET((Field*)(F)))#define SET_FIELD(T,O,F,V) *(T*)((char*)(O) + FIELD_BOFFSET((Field*)(F))) = (V)#define GET_STATIC_FIELD(T,F) *(T*)FIELD_ADDRESS((Field*)F)#define SET_STATIC_FIELD(T,F,V) *(T*)FIELD_ADDRESS((Field*)F) = (V)extern struct JNINativeInterface Kaffe_JNINativeInterface;extern JavaVMInitArgs Kaffe_JavaVMInitArgs;extern JavaVM Kaffe_JavaVM;static void Kaffe_JNI_wrapper(Method*, void*);#if defined(TRANSLATOR)static void *startJNIcall(void);static void finishJNIcall(void);static void Kaffe_wrapper(Method* xmeth, void* func, bool use_JNI);#endifstatic jint Kaffe_GetVersion(JNIEnv*);static jclass Kaffe_FindClass(JNIEnv*, const char*);static jint Kaffe_ThrowNew(JNIEnv*, jclass, const char*);static jint Kaffe_Throw(JNIEnv* env, jobject obj);jintJNI_GetDefaultJavaVMInitArgs(JavaVMInitArgs* args){ if (args->version != ((java_major_version << 16) | java_minor_version)) { return (-1); } memcpy(args, &Kaffe_JavaVMInitArgs, sizeof(JavaVMInitArgs)); args->version = (java_major_version << 16) | java_minor_version; return (0);}jintJNI_CreateJavaVM(JavaVM** vm, JNIEnv** env, JavaVMInitArgs* args){ if (args->version != ((java_major_version << 16) | java_minor_version)) { return (-1); } /* We can only init. one KVM */ if (Kaffe_NumVM != 0) { return (-1); } /* Setup the machine */ Kaffe_JavaVMArgs[0] = *args; initialiseKaffe(); /* Setup JNI for main thread */#if defined(NEED_JNIREFS) THREAD_DATA()->jnireferences = (jnirefs *)gc_malloc(sizeof(jnirefs), &gcNormal);#endif /* Return the VM and JNI we're using */ *vm = &Kaffe_JavaVM; *env = THREAD_JNIENV(); Kaffe_NumVM++;#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_JVM_INIT_DONE) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_JVM_INIT_DONE; jvmpiPostEvent(&ev); }#endif return (0);}jintJNI_GetCreatedJavaVMs(JavaVM** vm, jsize buflen, jsize* nvm){ vm[0] = &Kaffe_JavaVM; *nvm = Kaffe_NumVM; return (0);}/* * Everything from this point to Kaffe_GetVersion is not * exception-aware. Asynchronous exceptions should not be delivered * to them. * * Everything from Kaffe_GetVersion to Kaffe_GetJavaVM * should be bracketed with BEGIN and END _EXCEPTION_HANDLING. */static voidKaffe_FatalError(JNIEnv* env, const char* mess){ kprintf(stderr, "FATAL ERROR: %s\n", mess); exit(1);}static voidKaffe_DeleteGlobalRef(JNIEnv* env, jref obj){#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_JNI_GLOBALREF_FREE) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_JNI_GLOBALREF_FREE; ev.u.jni_globalref_free.ref_id = obj; jvmpiPostEvent(&ev); }#endif gc_rm_ref(obj);}static voidKaffe_DeleteLocalRef(JNIEnv* env, jref obj){ REMOVE_REF(obj);}static jbooleanKaffe_IsSameObject(JNIEnv* env, jobject obj1, jobject obj2){ if (obj1 == obj2) { return (JNI_TRUE); } else { return (JNI_FALSE); }}static voidKaffe_ReleaseStringChars(JNIEnv* env, jstring data, const jchar* chars){ /* Does nothing */}static jintKaffe_GetVersion(JNIEnv* env){ return ((java_major_version << 16) | java_minor_version);}/* * take a VM error and throw it as JNI error */static voidpostError(JNIEnv* env, errorInfo* info){ Kaffe_Throw(env, error2Throwable(info));}static jrefKaffe_NewGlobalRef(JNIEnv* env, jref obj){ BEGIN_EXCEPTION_HANDLING(0); if (!gc_add_ref(obj)) { errorInfo info; postOutOfMemory(&info); postError(env, &info); }#if defined(ENABLE_JVMPI) if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_JNI_GLOBALREF_ALLOC) ) { JVMPI_Event ev; ev.event_type = JVMPI_EVENT_JNI_GLOBALREF_ALLOC; ev.u.jni_globalref_alloc.obj_id = obj; ev.u.jni_globalref_alloc.ref_id = obj; jvmpiPostEvent(&ev); }#endif END_EXCEPTION_HANDLING(); return obj;}static jclassKaffe_DefineClass(JNIEnv* env, jobject loader, const jbyte* buf, jsize len){ Hjava_lang_Class* cls; classFile hand; errorInfo info; BEGIN_EXCEPTION_HANDLING(0); classFileInit(&hand, buf, len, CP_BYTEARRAY); cls = newClass(); if (cls == 0) { postOutOfMemory(&info); } else { cls = readClass(cls, &hand, loader, &info); } if (cls == 0) { postError(env, &info); } END_EXCEPTION_HANDLING(); return (cls);}/* * For this routine, we defer most of the work to Class.forName(), * which handles the task of figuring out the right ClassLoader to * use based on the calling method, which requires examining the * stack backtrace. */static jclassKaffe_FindClass(JNIEnv* env, const char* name){ jstring nameString; Utf8Const* utf8; jvalue retval; BEGIN_EXCEPTION_HANDLING(0); /* We accepts slashes, but Class.forName() does not */ utf8 = checkPtr(utf8ConstNew(name, -1)); nameString = utf8Const2JavaReplace(utf8, '/', '.'); utf8ConstRelease(utf8); checkPtr(nameString); /* Call Class.forName() */ retval = do_execute_java_class_method("java.lang.Class", NULL, "forName", "(Ljava/lang/String;)Ljava/lang/Class;", nameString); ADD_REF(retval.l); END_EXCEPTION_HANDLING(); return (retval.l);}static jclassKaffe_GetSuperClass(JNIEnv* env, jclass cls){ jclass ret; BEGIN_EXCEPTION_HANDLING(0); ret = ((Hjava_lang_Class*)cls)->superclass; END_EXCEPTION_HANDLING(); return (ret);}static jboolKaffe_IsAssignableFrom(JNIEnv* env, jclass cls1, jclass cls2){ jbool ret; BEGIN_EXCEPTION_HANDLING(0); if (instanceof(cls2, cls1) != 0) { ret = JNI_TRUE; } else { ret = JNI_FALSE; } END_EXCEPTION_HANDLING(); return (ret);}static jintKaffe_Throw(JNIEnv* env, jobject obj){ BEGIN_EXCEPTION_HANDLING(0); if( obj ) { assert(((Hjava_lang_Object *)obj)->dtable); thread_data->exceptObj = (struct Hjava_lang_Throwable*)obj; } END_EXCEPTION_HANDLING(); return (0);}static jintKaffe_ThrowNew(JNIEnv* env, jclass cls, const char* mess){ Hjava_lang_Object* eobj; BEGIN_EXCEPTION_HANDLING(0); eobj = execute_java_constructor(NULL, NULL, cls, "(Ljava/lang/String;)V", checkPtr(stringC2Java((char*)mess))); thread_data->exceptObj = (struct Hjava_lang_Throwable*)eobj; END_EXCEPTION_HANDLING(); return (0);}static jobjectKaffe_ExceptionOccurred(JNIEnv* env){ jobject obj; BEGIN_EXCEPTION_HANDLING(0); obj = thread_data->exceptObj; ADD_REF(obj); END_EXCEPTION_HANDLING(); return (obj);}static jbooleanKaffe_ExceptionCheck(JNIEnv* env){ jboolean result; jobject obj; BEGIN_EXCEPTION_HANDLING(0); obj = thread_data->exceptObj; result = (obj == NULL) ? JNI_FALSE : JNI_TRUE; END_EXCEPTION_HANDLING(); return (result);}static voidKaffe_ExceptionDescribe(JNIEnv* env){ BEGIN_EXCEPTION_HANDLING_VOID(); if (thread_data->exceptObj != 0) { do_execute_java_method(thread_data->exceptObj, "printStackTrace", "()V", 0, 0, thread_data->exceptObj); } END_EXCEPTION_HANDLING();}static voidKaffe_ExceptionClear(JNIEnv* env){ BEGIN_EXCEPTION_HANDLING_VOID(); thread_data->exceptObj = 0; END_EXCEPTION_HANDLING();}static jobjectKaffe_AllocObject(JNIEnv* env, jclass cls){ jobject obj; Hjava_lang_Class* clazz; BEGIN_EXCEPTION_HANDLING(0); clazz = (Hjava_lang_Class*)cls; if (CLASS_IS_INTERFACE(clazz) || CLASS_IS_ABSTRACT(clazz)) { throwException(InstantiationException(clazz->name->data)); } obj = newObject(clazz); ADD_REF(obj); END_EXCEPTION_HANDLING(); return (obj);}static jobjectKaffe_NewObjectV(JNIEnv* env, jclass cls, jmethodID meth, va_list args){ Hjava_lang_Object* obj; Hjava_lang_Class* clazz; jvalue retval; Method* m = (Method*)meth; BEGIN_EXCEPTION_HANDLING(0); clazz = (Hjava_lang_Class*)cls; if (CLASS_IS_INTERFACE(clazz) || CLASS_IS_ABSTRACT(clazz) || !METHOD_IS_CONSTRUCTOR(m)) { throwException(InstantiationException(clazz->name->data)); } obj = newObject(clazz); callMethodV(m, METHOD_INDIRECTMETHOD(m), obj, args, &retval); ADD_REF(obj); END_EXCEPTION_HANDLING(); return (obj);}static jobjectKaffe_NewObject(JNIEnv* env, jclass cls, jmethodID meth, ...){ jobject obj; va_list args; BEGIN_EXCEPTION_HANDLING(0); va_start(args, meth); obj = Kaffe_NewObjectV(env, cls, meth, args); va_end(args); END_EXCEPTION_HANDLING(); return (obj);}static jobjectKaffe_NewObjectA(JNIEnv* env, jclass cls, jmethodID meth, jvalue* args){ Hjava_lang_Object* obj; Hjava_lang_Class* clazz; jvalue retval; Method* m = (Method*)meth; BEGIN_EXCEPTION_HANDLING(0); clazz = (Hjava_lang_Class*)cls; if (CLASS_IS_INTERFACE(clazz) || CLASS_IS_ABSTRACT(clazz) || !METHOD_IS_CONSTRUCTOR(m)) { throwException(InstantiationException(clazz->name->data)); } obj = newObject(clazz); callMethodA(m, METHOD_INDIRECTMETHOD(m), obj, args, &retval, 0); ADD_REF(obj); END_EXCEPTION_HANDLING(); return (obj);}static jclassKaffe_GetObjectClass(JNIEnv* env, jobject obj){ jclass cls; BEGIN_EXCEPTION_HANDLING(0); cls = ((Hjava_lang_Object*)obj)->dtable->class; END_EXCEPTION_HANDLING(); return (cls);}static jboolKaffe_IsInstanceOf(JNIEnv* env, jobject obj, jclass cls){ jbool ret; BEGIN_EXCEPTION_HANDLING(0); if (soft_instanceof((Hjava_lang_Class*)cls, (Hjava_lang_Object*)obj) != 0) { ret = JNI_TRUE; } else { ret = JNI_FALSE; } END_EXCEPTION_HANDLING(); return (ret);}static jmethodIDKaffe_GetMethodID(JNIEnv* env, jclass cls, const char* name, const char* sig){ Method* meth; errorInfo info; BEGIN_EXCEPTION_HANDLING(0); meth = lookupClassMethod((Hjava_lang_Class*)cls, (char*)name, (char*)sig, &info); if (meth == 0) { postError(env, &info); } else if (METHOD_IS_STATIC(meth)) { postExceptionMessage(&info, JAVA_LANG(NoSuchMethodError), "%s", name); postError(env, &info); meth = 0; } END_EXCEPTION_HANDLING(); return (meth);}static jobjectKaffe_CallObjectMethodV(JNIEnv* env, jobject obj, jmethodID meth, va_list args){ jvalue retval; Hjava_lang_Object* o = (Hjava_lang_Object*)obj; Method* m = (Method*)meth; BEGIN_EXCEPTION_HANDLING(0); if (METHOD_IS_STATIC(m)) { throwException(NoSuchMethodError(m->name->data));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -