X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=libjava%2Fjni.cc;h=be79ba95d9f265e99af8feee6efe322019f53878;hb=b5c3a300438b1849515bf15bc340f27668e33f81;hp=82105a4d66f72ec425faea5b31348aa92a4a259e;hpb=3db5a98c3247be0dd8c39aa8801a430567289986;p=pf3gnuchains%2Fgcc-fork.git diff --git a/libjava/jni.cc b/libjava/jni.cc index 82105a4d66f..be79ba95d9f 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -1,6 +1,6 @@ // jni.cc - JNI implementation, including the jump table. -/* Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation This file is part of libgcj. @@ -20,6 +20,9 @@ details. */ #include #include #include +#ifdef ENABLE_JVMPI +#include +#endif #include #include @@ -36,19 +39,21 @@ details. */ #include #include #include +#include +#include #include #include #include -#define ClassClass _CL_Q34java4lang5Class -extern java::lang::Class ClassClass; -#define ObjectClass _CL_Q34java4lang6Object -extern java::lang::Class ObjectClass; - -#define MethodClass _CL_Q44java4lang7reflect6Method -extern java::lang::Class MethodClass; +// FIXME: remove these defines. +#define ClassClass java::lang::Class::class$ +#define ObjectClass java::lang::Object::class$ +#define ThrowableClass java::lang::Throwable::class$ +#define MethodClass java::lang::reflect::Method::class$ +#define ThreadGroupClass java::lang::ThreadGroup::class$ +#define NativeThreadClass gnu::gcj::jni::NativeThread::class$ // This enum is used to select different template instantiations in // the invocation code. @@ -60,22 +65,30 @@ enum invocation_type constructor }; -// Forward declaration. +// Forward declarations. extern struct JNINativeInterface _Jv_JNIFunctions; +extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions; // Number of slots in the default frame. The VM must allow at least // 16. #define FRAME_SIZE 32 +// Mark value indicating this is an overflow frame. +#define MARK_NONE 0 +// Mark value indicating this is a user frame. +#define MARK_USER 1 +// Mark value indicating this is a system frame. +#define MARK_SYSTEM 2 + // This structure is used to keep track of local references. struct _Jv_JNI_LocalFrame { // This is true if this frame object represents a pushed frame (eg // from PushLocalFrame). - int marker : 1; + int marker : 2; // Number of elements in frame. - int size : 31; + int size : 30; // Next frame in chain. _Jv_JNI_LocalFrame *next; @@ -87,12 +100,69 @@ struct _Jv_JNI_LocalFrame // This holds a reference count for all local and global references. static java::util::Hashtable *ref_table; +// The only VM. +static JavaVM *the_vm; + +#ifdef ENABLE_JVMPI +// The only JVMPI interface description. +static JVMPI_Interface _Jv_JVMPI_Interface; + +static jint +jvmpiEnableEvent (jint event_type, void *) +{ + switch (event_type) + { + case JVMPI_EVENT_OBJECT_ALLOC: + _Jv_JVMPI_Notify_OBJECT_ALLOC = _Jv_JVMPI_Interface.NotifyEvent; + break; + + case JVMPI_EVENT_THREAD_START: + _Jv_JVMPI_Notify_THREAD_START = _Jv_JVMPI_Interface.NotifyEvent; + break; + + case JVMPI_EVENT_THREAD_END: + _Jv_JVMPI_Notify_THREAD_END = _Jv_JVMPI_Interface.NotifyEvent; + break; + + default: + return JVMPI_NOT_AVAILABLE; + } + + return JVMPI_SUCCESS; +} + +static jint +jvmpiDisableEvent (jint event_type, void *) +{ + switch (event_type) + { + case JVMPI_EVENT_OBJECT_ALLOC: + _Jv_JVMPI_Notify_OBJECT_ALLOC = NULL; + break; + + default: + return JVMPI_NOT_AVAILABLE; + } + + return JVMPI_SUCCESS; +} +#endif + void _Jv_JNI_Init (void) { ref_table = new java::util::Hashtable; + +#ifdef ENABLE_JVMPI + _Jv_JVMPI_Interface.version = 1; + _Jv_JVMPI_Interface.EnableEvent = &jvmpiEnableEvent; + _Jv_JVMPI_Interface.DisableEvent = &jvmpiDisableEvent; + _Jv_JVMPI_Interface.EnableGC = &_Jv_EnableGC; + _Jv_JVMPI_Interface.DisableGC = &_Jv_DisableGC; + _Jv_JVMPI_Interface.RunGC = &_Jv_RunGC; +#endif } // Tell the GC that a certain pointer is live. @@ -104,6 +174,7 @@ mark_for_gc (jobject obj) using namespace java::lang; Integer *refcount = (Integer *) ref_table->get (obj); jint val = (refcount == NULL) ? 0 : refcount->intValue (); + // FIXME: what about out of memory error? ref_table->put (obj, new Integer (val + 1)); } @@ -120,6 +191,7 @@ unmark_for_gc (jobject obj) if (val == 0) ref_table->remove (obj); else + // FIXME: what about out of memory error? ref_table->put (obj, new Integer (val)); } @@ -156,7 +228,7 @@ _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj) } // Don't go past a marked frame. - JvAssert (! frame->marker); + JvAssert (frame->marker == MARK_NONE); } JvAssert (0); @@ -169,17 +241,19 @@ _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size) // size. This isn't the most efficient thing, but for now we don't // care. Note that _Jv_JNI_PushLocalFrame relies on this right now. - _Jv_JNI_LocalFrame *frame - = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame) - + size * sizeof (jobject)); - if (frame == NULL) + _Jv_JNI_LocalFrame *frame; + try + { + frame = (_Jv_JNI_LocalFrame *) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame) + + size * sizeof (jobject)); + } + catch (jthrowable t) { - // FIXME: exception processing. - env->ex = new java::lang::OutOfMemoryError; - return -1; + env->ex = t; + return JNI_ERR; } - frame->marker = true; + frame->marker = MARK_NONE; frame->size = size; memset (&frame->vec[0], 0, size * sizeof (jobject)); frame->next = env->locals; @@ -196,7 +270,7 @@ _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size) return r; // The new frame is on top. - env->locals->marker = true; + env->locals->marker = MARK_USER; return 0; } @@ -233,7 +307,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj) } static jobject -_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) +_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop) { _Jv_JNI_LocalFrame *rf = env->locals; @@ -245,7 +319,7 @@ _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) unmark_for_gc (rf->vec[i]); // If the frame we just freed is the marker frame, we are done. - done = rf->marker; + done = (rf->marker == stop); _Jv_JNI_LocalFrame *n = rf->next; // When N==NULL, we've reached the stack-allocated frame, and we @@ -264,6 +338,27 @@ _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result); } +static jobject +_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) +{ + return _Jv_JNI_PopLocalFrame (env, result, MARK_USER); +} + +// Pop a `system' frame from the stack. This is `extern "C"' as it is +// used by the compiler. +extern "C" void +_Jv_JNI_PopSystemFrame (JNIEnv *env) +{ + _Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM); + + if (env->ex) + { + jthrowable t = env->ex; + env->ex = NULL; + throw t; + } +} + // This function is used from other template functions. It wraps the // return value appropriately; we specialize it so that object returns // are turned into local references. @@ -278,7 +373,7 @@ template<> static jobject wrap_value (JNIEnv *env, jobject value) { - return _Jv_JNI_NewLocalRef (env, value); + return value == NULL ? value : _Jv_JNI_NewLocalRef (env, value); } @@ -293,16 +388,24 @@ static jclass _Jv_JNI_DefineClass (JNIEnv *env, jobject loader, const jbyte *buf, jsize bufLen) { - jbyteArray bytes = JvNewByteArray (bufLen); - jbyte *elts = elements (bytes); - memcpy (elts, buf, bufLen * sizeof (jbyte)); + try + { + jbyteArray bytes = JvNewByteArray (bufLen); + + jbyte *elts = elements (bytes); + memcpy (elts, buf, bufLen * sizeof (jbyte)); - java::lang::ClassLoader *l - = reinterpret_cast (loader); + java::lang::ClassLoader *l + = reinterpret_cast (loader); - // FIXME: exception processing. - jclass result = l->defineClass (bytes, 0, bufLen); - return (jclass) _Jv_JNI_NewLocalRef (env, result); + jclass result = l->defineClass (bytes, 0, bufLen); + return (jclass) wrap_value (env, result); + } + catch (jthrowable t) + { + env->ex = t; + return NULL; + } } static jclass @@ -313,28 +416,38 @@ _Jv_JNI_FindClass (JNIEnv *env, const char *name) char s[len + 1]; for (int i = 0; i <= len; ++i) s[i] = (name[i] == '/') ? '.' : name[i]; - jstring n = JvNewStringUTF (s); - java::lang::ClassLoader *loader; - if (env->klass == NULL) + jclass r = NULL; + try { - // FIXME: should use getBaseClassLoader, but we don't have that - // yet. - loader = java::lang::ClassLoader::getSystemClassLoader (); - } - else - loader = env->klass->getClassLoader (); + // This might throw an out of memory exception. + jstring n = JvNewStringUTF (s); - // FIXME: exception processing. - jclass r = loader->findClass (n); + java::lang::ClassLoader *loader = NULL; + if (env->klass != NULL) + loader = env->klass->getClassLoader (); - return (jclass) _Jv_JNI_NewLocalRef (env, r); + if (loader == NULL) + { + // FIXME: should use getBaseClassLoader, but we don't have that + // yet. + loader = java::lang::ClassLoader::getSystemClassLoader (); + } + + r = loader->loadClass (n); + } + catch (jthrowable t) + { + env->ex = t; + } + + return (jclass) wrap_value (env, r); } static jclass _Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz) { - return (jclass) _Jv_JNI_NewLocalRef (env, clazz->getSuperclass ()); + return (jclass) wrap_value (env, clazz->getSuperclass ()); } static jboolean @@ -346,6 +459,8 @@ _Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2) static jint _Jv_JNI_Throw (JNIEnv *env, jthrowable obj) { + // We check in case the user did some funky cast. + JvAssert (obj != NULL && (&ThrowableClass)->isInstance (obj)); env->ex = obj; return 0; } @@ -355,30 +470,40 @@ _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message) { using namespace java::lang::reflect; - JArray *argtypes - = (JArray *) JvNewObjectArray (1, &ClassClass, NULL); + JvAssert ((&ThrowableClass)->isAssignableFrom (clazz)); - jclass *elts = elements (argtypes); - elts[0] = &StringClass; + int r = JNI_OK; + try + { + JArray *argtypes + = (JArray *) JvNewObjectArray (1, &ClassClass, NULL); - // FIXME: exception processing. - Constructor *cons = clazz->getConstructor (argtypes); + jclass *elts = elements (argtypes); + elts[0] = &StringClass; - jobjectArray values = JvNewObjectArray (1, &StringClass, NULL); - jobject *velts = elements (values); - velts[0] = JvNewStringUTF (message); + Constructor *cons = clazz->getConstructor (argtypes); - // FIXME: exception processing. - jobject obj = cons->newInstance (values); + jobjectArray values = JvNewObjectArray (1, &StringClass, NULL); + jobject *velts = elements (values); + velts[0] = JvNewStringUTF (message); - env->ex = reinterpret_cast (obj); - return 0; + jobject obj = cons->newInstance (values); + + env->ex = reinterpret_cast (obj); + } + catch (jthrowable t) + { + env->ex = t; + r = JNI_ERR; + } + + return r; } static jthrowable _Jv_JNI_ExceptionOccurred (JNIEnv *env) { - return (jthrowable) _Jv_JNI_NewLocalRef (env, env->ex); + return (jthrowable) wrap_value (env, env->ex); } static void @@ -419,22 +544,31 @@ _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz) { jobject obj = NULL; using namespace java::lang::reflect; - if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers())) - env->ex = new java::lang::InstantiationException (); - else + + try { - // FIXME: exception processing. - // FIXME: will this work for String? - obj = JvAllocObject (clazz); + JvAssert (clazz && ! clazz->isArray ()); + if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers())) + env->ex = new java::lang::InstantiationException (); + else + { + // FIXME: will this work for String? + obj = JvAllocObject (clazz); + } + } + catch (jthrowable t) + { + env->ex = t; } - return _Jv_JNI_NewLocalRef (env, obj); + return wrap_value (env, obj); } static jclass _Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj) { - return (jclass) _Jv_JNI_NewLocalRef (env, obj->getClass()); + JvAssert (obj); + return (jclass) wrap_value (env, obj->getClass()); } static jboolean @@ -454,36 +588,49 @@ static jmethodID _Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz, const char *name, const char *sig) { - // FIXME: exception processing. - _Jv_InitClass (clazz); + try + { + _Jv_InitClass (clazz); - _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1); - _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1); + _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1); - JvAssert (! clazz->isPrimitive()); + // FIXME: assume that SIG isn't too long. + int len = strlen (sig); + char s[len + 1]; + for (int i = 0; i <= len; ++i) + s[i] = (sig[i] == '/') ? '.' : sig[i]; + _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) s, -1); - using namespace java::lang::reflect; + JvAssert (! clazz->isPrimitive()); - while (clazz != NULL) - { - jint count = JvNumMethods (clazz); - jmethodID meth = JvGetFirstMethod (clazz); + using namespace java::lang::reflect; - for (jint i = 0; i < count; ++i) + while (clazz != NULL) { - if (((is_static && Modifier::isStatic (meth->accflags)) - || (! is_static && ! Modifier::isStatic (meth->accflags))) - && _Jv_equalUtf8Consts (meth->name, name_u) - && _Jv_equalUtf8Consts (meth->signature, sig_u)) - return meth; + jint count = JvNumMethods (clazz); + jmethodID meth = JvGetFirstMethod (clazz); + + for (jint i = 0; i < count; ++i) + { + if (((is_static && Modifier::isStatic (meth->accflags)) + || (! is_static && ! Modifier::isStatic (meth->accflags))) + && _Jv_equalUtf8Consts (meth->name, name_u) + && _Jv_equalUtf8Consts (meth->signature, sig_u)) + return meth; + + meth = meth->getNextMethod(); + } - meth = meth->getNextMethod(); + clazz = clazz->getSuperclass (); } - clazz = clazz->getSuperclass (); + env->ex = new java::lang::NoSuchMethodError (); + } + catch (jthrowable t) + { + env->ex = t; } - env->ex = new java::lang::NoSuchMethodError (); return NULL; } @@ -535,23 +682,36 @@ _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass, jclass return_type; JArray *arg_types; - // FIXME: exception processing. - _Jv_GetTypesFromSignature (id, decl_class, - &arg_types, &return_type); - jvalue args[arg_types->length]; - array_from_valist (args, arg_types, vargs); + try + { + _Jv_GetTypesFromSignature (id, decl_class, + &arg_types, &return_type); + + jvalue args[arg_types->length]; + array_from_valist (args, arg_types, vargs); + + // For constructors we need to pass the Class we are instantiating. + if (style == constructor) + return_type = klass; - jvalue result; - jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, - style == constructor, - arg_types, args, &result); + jvalue result; + jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, + style == constructor, + arg_types, args, &result); - if (ex != NULL) - env->ex = ex; + if (ex != NULL) + env->ex = ex; - // We cheat a little here. FIXME. - return wrap_value (env, * (T *) &result); + // We cheat a little here. FIXME. + return wrap_value (env, * (T *) &result); + } + catch (jthrowable t) + { + env->ex = t; + } + + return wrap_value (env, (T) 0); } template @@ -582,20 +742,32 @@ _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass, jclass return_type; JArray *arg_types; - // FIXME: exception processing. - _Jv_GetTypesFromSignature (id, decl_class, - &arg_types, &return_type); + try + { + _Jv_GetTypesFromSignature (id, decl_class, + &arg_types, &return_type); + + // For constructors we need to pass the Class we are instantiating. + if (style == constructor) + return_type = klass; - jvalue result; - jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, - style == constructor, - arg_types, args, &result); + jvalue result; + jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, + style == constructor, + arg_types, args, &result); - if (ex != NULL) - env->ex = ex; + if (ex != NULL) + env->ex = ex; - // We cheat a little here. FIXME. - return wrap_value (env, * (T *) &result); + // We cheat a little here. FIXME. + return wrap_value (env, * (T *) &result); + } + catch (jthrowable t) + { + env->ex = t; + } + + return wrap_value (env, (T) 0); } template @@ -611,19 +783,29 @@ _Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass, jclass return_type; JArray *arg_types; - // FIXME: exception processing. - _Jv_GetTypesFromSignature (id, decl_class, - &arg_types, &return_type); + try + { + _Jv_GetTypesFromSignature (id, decl_class, + &arg_types, &return_type); + + jvalue args[arg_types->length]; + array_from_valist (args, arg_types, vargs); - jvalue args[arg_types->length]; - array_from_valist (args, arg_types, vargs); + // For constructors we need to pass the Class we are instantiating. + if (style == constructor) + return_type = klass; - jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, - style == constructor, - arg_types, args, NULL); + jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, + style == constructor, + arg_types, args, NULL); - if (ex != NULL) - env->ex = ex; + if (ex != NULL) + env->ex = ex; + } + catch (jthrowable t) + { + env->ex = t; + } } template @@ -651,16 +833,22 @@ _Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass, jclass return_type; JArray *arg_types; - // FIXME: exception processing. - _Jv_GetTypesFromSignature (id, decl_class, - &arg_types, &return_type); + try + { + _Jv_GetTypesFromSignature (id, decl_class, + &arg_types, &return_type); - jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, - style == constructor, - arg_types, args, NULL); + jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id, + style == constructor, + arg_types, args, NULL); - if (ex != NULL) - env->ex = ex; + if (ex != NULL) + env->ex = ex; + } + catch (jthrowable t) + { + env->ex = t; + } } // Functions with this signature are used to implement functions in @@ -726,6 +914,9 @@ static T _Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass, jmethodID id, va_list args) { + JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC)); + JvAssert ((&ClassClass)->isInstance (klass)); + return _Jv_JNI_CallAnyMethodV (env, NULL, klass, id, args); } @@ -738,6 +929,9 @@ _Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...) va_list args; T result; + JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC)); + JvAssert ((&ClassClass)->isInstance (klass)); + va_start (args, id); result = _Jv_JNI_CallAnyMethodV (env, NULL, klass, id, args); @@ -753,6 +947,9 @@ static T _Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id, jvalue *args) { + JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC)); + JvAssert ((&ClassClass)->isInstance (klass)); + return _Jv_JNI_CallAnyMethodA (env, NULL, klass, id, args); } @@ -784,6 +981,13 @@ static jobject _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass, jmethodID id, va_list args) { + JvAssert (klass && ! klass->isArray ()); + JvAssert (! strcmp (id->name->data, "") + && id->signature->length > 2 + && id->signature->data[0] == '(' + && ! strcmp (&id->signature->data[id->signature->length - 2], + ")V")); + return _Jv_JNI_CallAnyMethodV (env, NULL, klass, id, args); } @@ -791,6 +995,13 @@ _Jv_JNI_NewObjectV (JNIEnv *env, jclass klass, static jobject _Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...) { + JvAssert (klass && ! klass->isArray ()); + JvAssert (! strcmp (id->name->data, "") + && id->signature->length > 2 + && id->signature->data[0] == '(' + && ! strcmp (&id->signature->data[id->signature->length - 2], + ")V")); + va_list args; jobject result; @@ -806,6 +1017,13 @@ static jobject _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id, jvalue *args) { + JvAssert (klass && ! klass->isArray ()); + JvAssert (! strcmp (id->name->data, "") + && id->signature->length > 2 + && id->signature->data[0] == '(' + && ! strcmp (&id->signature->data[id->signature->length - 2], + ")V")); + return _Jv_JNI_CallAnyMethodA (env, NULL, klass, id, args); } @@ -816,6 +1034,7 @@ template static T _Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field) { + JvAssert (obj); T *ptr = (T *) ((char *) obj + field->getOffset ()); return wrap_value (env, *ptr); } @@ -824,6 +1043,7 @@ template static void _Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value) { + JvAssert (obj); T *ptr = (T *) ((char *) obj + field->getOffset ()); *ptr = value; } @@ -833,49 +1053,53 @@ static jfieldID _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) { - // FIXME: exception processing. - _Jv_InitClass (clazz); + try + { + _Jv_InitClass (clazz); - _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1); + _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1); - jclass field_class = NULL; - if (sig[0] == '[') - field_class = _Jv_FindClassFromSignature ((char *) sig, NULL); - else - { - _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1); - field_class = _Jv_FindClass (sig_u, NULL); - } + // FIXME: assume that SIG isn't too long. + int len = strlen (sig); + char s[len + 1]; + for (int i = 0; i <= len; ++i) + s[i] = (sig[i] == '/') ? '.' : sig[i]; + jclass field_class = _Jv_FindClassFromSignature ((char *) s, NULL); - // FIXME: what if field_class == NULL? + // FIXME: what if field_class == NULL? - while (clazz != NULL) - { - jint count = (is_static - ? JvNumStaticFields (clazz) - : JvNumInstanceFields (clazz)); - jfieldID field = (is_static - ? JvGetFirstStaticField (clazz) - : JvGetFirstInstanceField (clazz)); - for (jint i = 0; i < count; ++i) + while (clazz != NULL) { - // The field is resolved as a side effect of class - // initialization. - JvAssert (field->isResolved ()); + jint count = (is_static + ? JvNumStaticFields (clazz) + : JvNumInstanceFields (clazz)); + jfieldID field = (is_static + ? JvGetFirstStaticField (clazz) + : JvGetFirstInstanceField (clazz)); + for (jint i = 0; i < count; ++i) + { + // The field is resolved as a side effect of class + // initialization. + JvAssert (field->isResolved ()); + + _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz); - _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz); + if (_Jv_equalUtf8Consts (f_name, a_name) + && field->getClass() == field_class) + return field; - if (_Jv_equalUtf8Consts (f_name, a_name) - && field->getClass() == field_class) - return field; + field = field->getNextField (); + } - field = field->getNextField (); + clazz = clazz->getSuperclass (); } - clazz = clazz->getSuperclass (); + env->ex = new java::lang::NoSuchFieldError (); + } + catch (jthrowable t) + { + env->ex = t; } - - env->ex = new java::lang::NoSuchFieldError (); return NULL; } @@ -898,9 +1122,16 @@ _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value) static jstring _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len) { - // FIXME: exception processing. - jstring r = _Jv_NewString (unichars, len); - return (jstring) _Jv_JNI_NewLocalRef (env, r); + try + { + jstring r = _Jv_NewString (unichars, len); + return (jstring) wrap_value (env, r); + } + catch (jthrowable t) + { + env->ex = t; + return NULL; + } } static jsize @@ -928,9 +1159,16 @@ _Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *) static jstring _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes) { - // FIXME: exception processing. - jstring result = JvNewStringUTF (bytes); - return (jstring) _Jv_JNI_NewLocalRef (env, result); + try + { + jstring result = JvNewStringUTF (bytes); + return (jstring) wrap_value (env, result); + } + catch (jthrowable t) + { + env->ex = t; + return NULL; + } } static jsize @@ -940,18 +1178,25 @@ _Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string) } static const char * -_Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy) +_Jv_JNI_GetStringUTFChars (JNIEnv *env, jstring string, jboolean *isCopy) { jsize len = JvGetStringUTFLength (string); - // FIXME: exception processing. - char *r = (char *) _Jv_Malloc (len + 1); - JvGetStringUTFRegion (string, 0, len, r); - r[len] = '\0'; + try + { + char *r = (char *) _Jv_Malloc (len + 1); + JvGetStringUTFRegion (string, 0, len, r); + r[len] = '\0'; - if (isCopy) - *isCopy = true; + if (isCopy) + *isCopy = true; - return (const char *) r; + return (const char *) r; + } + catch (jthrowable t) + { + env->ex = t; + return NULL; + } } static void @@ -967,7 +1212,16 @@ _Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len, jchar *result = _Jv_GetStringChars (string); if (start < 0 || start > string->length () || len < 0 || start + len > string->length ()) - env->ex = new java::lang::StringIndexOutOfBoundsException (); + { + try + { + env->ex = new java::lang::StringIndexOutOfBoundsException (); + } + catch (jthrowable t) + { + env->ex = t; + } + } else memcpy (buf, &result[start], len * sizeof (jchar)); } @@ -978,7 +1232,16 @@ _Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start, { if (start < 0 || start > str->length () || len < 0 || start + len > str->length ()) - env->ex = new java::lang::StringIndexOutOfBoundsException (); + { + try + { + env->ex = new java::lang::StringIndexOutOfBoundsException (); + } + catch (jthrowable t) + { + env->ex = t; + } + } else _Jv_GetStringUTFRegion (str, start, len, buf); } @@ -1008,35 +1271,54 @@ static jarray _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass, jobject init) { - // FIXME: exception processing. - jarray result = JvNewObjectArray (length, elementClass, init); - return (jarray) _Jv_JNI_NewLocalRef (env, result); + try + { + jarray result = JvNewObjectArray (length, elementClass, init); + return (jarray) wrap_value (env, result); + } + catch (jthrowable t) + { + env->ex = t; + return NULL; + } } static jobject _Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index) { jobject *elts = elements (array); - return _Jv_JNI_NewLocalRef (env, elts[index]); + return wrap_value (env, elts[index]); } static void -_Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index, +_Jv_JNI_SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobject value) { - // FIXME: exception processing. - _Jv_CheckArrayStore (array, value); - jobject *elts = elements (array); - elts[index] = value; + try + { + _Jv_CheckArrayStore (array, value); + jobject *elts = elements (array); + elts[index] = value; + } + catch (jthrowable t) + { + env->ex = t; + } } template static JArray * _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length) { - // FIXME: exception processing. - return (JArray *) _Jv_JNI_NewLocalRef (env, - _Jv_NewPrimArray (K, length)); + try + { + return (JArray *) wrap_value (env, _Jv_NewPrimArray (K, length)); + } + catch (jthrowable t) + { + env->ex = t; + return NULL; + } } template @@ -1073,8 +1355,16 @@ _Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray *array, { if (start < 0 || len >= array->length || start + len >= array->length) { - // FIXME: index. - env->ex = new java::lang::ArrayIndexOutOfBoundsException (); + try + { + // FIXME: index. + env->ex = new java::lang::ArrayIndexOutOfBoundsException (); + } + catch (jthrowable t) + { + // Could have thown out of memory error. + env->ex = t; + } } else { @@ -1090,8 +1380,15 @@ _Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray *array, { if (start < 0 || len >= array->length || start + len >= array->length) { - // FIXME: index. - env->ex = new java::lang::ArrayIndexOutOfBoundsException (); + try + { + // FIXME: index. + env->ex = new java::lang::ArrayIndexOutOfBoundsException (); + } + catch (jthrowable t) + { + env->ex = t; + } } else { @@ -1120,19 +1417,31 @@ _Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint) } static jint -_Jv_JNI_MonitorEnter (JNIEnv *, jobject obj) +_Jv_JNI_MonitorEnter (JNIEnv *env, jobject obj) { - // FIXME: exception processing. - jint r = _Jv_MonitorEnter (obj); - return r; + try + { + return _Jv_MonitorEnter (obj); + } + catch (jthrowable t) + { + env->ex = t; + } + return JNI_ERR; } static jint -_Jv_JNI_MonitorExit (JNIEnv *, jobject obj) +_Jv_JNI_MonitorExit (JNIEnv *env, jobject obj) { - // FIXME: exception processing. - jint r = _Jv_MonitorExit (obj); - return r; + try + { + return _Jv_MonitorExit (obj); + } + catch (jthrowable t) + { + env->ex = t; + } + return JNI_ERR; } // JDK 1.2 @@ -1140,12 +1449,19 @@ jobject _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean) { - // FIXME: exception processing. - java::lang::reflect::Field *field = new java::lang::reflect::Field(); - field->declaringClass = cls; - field->offset = (char*) fieldID - (char *) cls->fields; - field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls)); - return _Jv_JNI_NewLocalRef (env, field); + try + { + java::lang::reflect::Field *field = new java::lang::reflect::Field(); + field->declaringClass = cls; + field->offset = (char*) fieldID - (char *) cls->fields; + field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls)); + return wrap_value (env, field); + } + catch (jthrowable t) + { + env->ex = t; + } + return NULL; } // JDK 1.2 @@ -1167,24 +1483,32 @@ _Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id, // FIXME. static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("", 6); - jobject result; - if (_Jv_equalUtf8Consts (id->name, init_name)) + jobject result = NULL; + + try { - // A constructor. - Constructor *cons = new Constructor (); - cons->offset = (char *) id - (char *) &klass->methods; - cons->declaringClass = klass; - result = cons; + if (_Jv_equalUtf8Consts (id->name, init_name)) + { + // A constructor. + Constructor *cons = new Constructor (); + cons->offset = (char *) id - (char *) &klass->methods; + cons->declaringClass = klass; + result = cons; + } + else + { + Method *meth = new Method (); + meth->offset = (char *) id - (char *) &klass->methods; + meth->declaringClass = klass; + result = meth; + } } - else + catch (jthrowable t) { - Method *meth = new Method (); - meth->offset = (char *) id - (char *) &klass->methods; - meth->declaringClass = klass; - result = meth; + env->ex = t; } - return _Jv_JNI_NewLocalRef (env, result); + return wrap_value (env, result); } static jmethodID @@ -1197,6 +1521,74 @@ _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method) _Jv_FromReflectedConstructor (reinterpret_cast (method)); } +static jint +_Jv_JNI_RegisterNatives (JNIEnv *env, jclass k, + const JNINativeMethod *methods, + jint nMethods) +{ +#ifdef INTERPRETER + // For now, this only matters for interpreted methods. FIXME. + if (! _Jv_IsInterpretedClass (k)) + { + // FIXME: throw exception. + return JNI_ERR; + } + _Jv_InterpClass *klass = reinterpret_cast<_Jv_InterpClass *> (k); + + // Look at each descriptor given us, and find the corresponding + // method in the class. + for (int j = 0; j < nMethods; ++j) + { + bool found = false; + + _Jv_MethodBase **imeths = _Jv_GetFirstMethod (klass); + for (int i = 0; i < JvNumMethods (klass); ++i) + { + _Jv_MethodBase *meth = imeths[i]; + _Jv_Method *self = meth->get_method (); + + if (! strcmp (self->name->data, methods[j].name) + && ! strcmp (self->signature->data, methods[j].signature)) + { + if (! (self->accflags + & java::lang::reflect::Modifier::NATIVE)) + break; + + // Found a match that is native. + _Jv_JNIMethod *jmeth = reinterpret_cast<_Jv_JNIMethod *> (meth); + jmeth->set_function (methods[i].fnPtr); + found = true; + break; + } + } + + if (! found) + { + jstring m = JvNewStringUTF (methods[j].name); + try + { + env->ex =new java::lang::NoSuchMethodError (m); + } + catch (jthrowable t) + { + env->ex = t; + } + return JNI_ERR; + } + } + + return JNI_OK; +#else /* INTERPRETER */ + return JNI_ERR; +#endif /* INTERPRETER */ +} + +static jint +_Jv_JNI_UnregisterNatives (JNIEnv *, jclass) +{ + return JNI_ERR; +} + #ifdef INTERPRETER @@ -1222,7 +1614,7 @@ add_char (char *buf, jchar c, int *here) } else if (c == '/') buf[(*here)++] = '_'; - if ((c >= '0' && c <= '9') + else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) buf[(*here)++] = (char) c; @@ -1278,8 +1670,9 @@ mangled_name (jclass klass, _Jv_Utf8Const *func_name, const unsigned char *sig = (const unsigned char *) signature->data; limit = sig + signature->length; - JvAssert (signature[0] == '('); - for (int i = 1; ; ++i) + JvAssert (sig[0] == '('); + ++sig; + while (1) { int ch = UTF8_GET (sig, limit); if (ch == ')' || ch < 0) @@ -1290,29 +1683,78 @@ mangled_name (jclass klass, _Jv_Utf8Const *func_name, buf[here] = '\0'; } -// This function is the stub which is used to turn an ordinary (CNI) -// method call into a JNI call. -void -_Jv_JNIMethod::call (ffi_cif *cif, void *ret, ffi_raw *args, void *__this) +// Return the current thread's JNIEnv; if one does not exist, create +// it. Also create a new system frame for use. This is `extern "C"' +// because the compiler calls it. +extern "C" JNIEnv * +_Jv_GetJNIEnvNewFrame (jclass klass) { - _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this; + JNIEnv *env = _Jv_GetCurrentJNIEnv (); + if (env == NULL) + { + env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv)); + env->p = &_Jv_JNIFunctions; + env->ex = NULL; + env->klass = klass; + env->locals = NULL; - JNIEnv env; - _Jv_JNI_LocalFrame *frame - = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame) - + FRAME_SIZE * sizeof (jobject)); + _Jv_SetCurrentJNIEnv (env); + } - env.p = &_Jv_JNIFunctions; - env.ex = NULL; - env.klass = _this->defining_class; - env.locals = frame; + _Jv_JNI_LocalFrame *frame + = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame) + + (FRAME_SIZE + * sizeof (jobject))); - frame->marker = true; - frame->next = NULL; + frame->marker = MARK_SYSTEM; frame->size = FRAME_SIZE; + frame->next = env->locals; + env->locals = frame; + for (int i = 0; i < frame->size; ++i) frame->vec[i] = NULL; + return env; +} + +// Return the function which implements a particular JNI method. If +// we can't find the function, we throw the appropriate exception. +// This is `extern "C"' because the compiler uses it. +extern "C" void * +_Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name, + _Jv_Utf8Const *signature) +{ + char buf[10 + 6 * (name->length + signature->length)]; + int long_start; + void *function; + + mangled_name (klass, name, signature, buf, &long_start); + char c = buf[long_start]; + buf[long_start] = '\0'; + function = _Jv_FindSymbolInExecutable (buf); + if (function == NULL) + { + buf[long_start] = c; + function = _Jv_FindSymbolInExecutable (buf); + if (function == NULL) + { + jstring str = JvNewStringUTF (name->data); + JvThrow (new java::lang::AbstractMethodError (str)); + } + } + + return function; +} + +// This function is the stub which is used to turn an ordinary (CNI) +// method call into a JNI call. +void +_Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) +{ + _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this; + + JNIEnv *env = _Jv_GetJNIEnvNewFrame (_this->defining_class); + // FIXME: we should mark every reference parameter as a local. For // now we assume a conservative GC, and we assume that the // references are on the stack somewhere. @@ -1321,42 +1763,316 @@ _Jv_JNIMethod::call (ffi_cif *cif, void *ret, ffi_raw *args, void *__this) // a value we don't cache that fact -- we might subsequently load a // library which finds the function in question. if (_this->function == NULL) + _this->function = _Jv_LookupJNIMethod (_this->defining_class, + _this->self->name, + _this->self->signature); + + JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0); + ffi_raw real_args[2 + _this->args_raw_size / sizeof (ffi_raw)]; + int offset = 0; + + // First argument is always the environment pointer. + real_args[offset++].ptr = env; + + // For a static method, we pass in the Class. For non-static + // methods, the `this' argument is already handled. + if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC)) + real_args[offset++].ptr = _this->defining_class; + + // Copy over passed-in arguments. + memcpy (&real_args[offset], args, _this->args_raw_size); + + // The actual call to the JNI function. + ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function, + ret, real_args); + + _Jv_JNI_PopSystemFrame (env); +} + +#endif /* INTERPRETER */ + + + +// +// Invocation API. +// + +// An internal helper function. +static jint +_Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv, void *args) +{ + JavaVMAttachArgs *attach = reinterpret_cast (args); + java::lang::ThreadGroup *group = NULL; + + if (attach) + { + // FIXME: do we really want to support 1.1? + if (attach->version != JNI_VERSION_1_2 + && attach->version != JNI_VERSION_1_1) + return JNI_EVERSION; + + JvAssert ((&ThreadGroupClass)->isInstance (attach->group)); + group = reinterpret_cast (attach->group); + } + + // Attaching an already-attached thread is a no-op. + if (_Jv_GetCurrentJNIEnv () != NULL) + return 0; + + JNIEnv *env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv)); + if (env == NULL) + return JNI_ERR; + env->p = &_Jv_JNIFunctions; + env->ex = NULL; + env->klass = NULL; + env->locals + = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame) + + (FRAME_SIZE + * sizeof (jobject))); + if (env->locals == NULL) + { + _Jv_Free (env); + return JNI_ERR; + } + *penv = reinterpret_cast (env); + + // This thread might already be a Java thread -- this function might + // have been called simply to set the new JNIEnv. + if (_Jv_ThreadCurrent () == NULL) { - char buf[10 + 6 * (_this->self->name->length - + _this->self->signature->length)]; - int long_start; - mangled_name (_this->defining_class, _this->self->name, - _this->self->signature, buf, &long_start); - char c = buf[long_start]; - buf[long_start] = '\0'; - _this->function = _Jv_FindSymbolInExecutable (buf); - if (_this->function == NULL) + try { - buf[long_start] = c; - _this->function = _Jv_FindSymbolInExecutable (buf); - if (_this->function == NULL) + (void) new gnu::gcj::jni::NativeThread (group, name); + } + catch (jthrowable t) + { + return JNI_ERR; + } + } + _Jv_SetCurrentJNIEnv (env); + + return 0; +} + +// This is the one actually used by JNI. +static jint +_Jv_JNI_AttachCurrentThread (JavaVM *vm, void **penv, void *args) +{ + return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args); +} + +static jint +_Jv_JNI_DestroyJavaVM (JavaVM *vm) +{ + JvAssert (the_vm && vm == the_vm); + + JNIEnv *env; + if (_Jv_ThreadCurrent () != NULL) + { + jstring main_name; + // This sucks. + try + { + main_name = JvNewStringLatin1 ("main"); + } + catch (jthrowable t) + { + return JNI_ERR; + } + + jint r = _Jv_JNI_AttachCurrentThread (vm, + main_name, + reinterpret_cast (&env), + NULL); + if (r < 0) + return r; + } + else + env = _Jv_GetCurrentJNIEnv (); + + _Jv_ThreadWait (); + + // Docs say that this always returns an error code. + return JNI_ERR; +} + +static jint +_Jv_JNI_DetachCurrentThread (JavaVM *) +{ + java::lang::Thread *t = _Jv_ThreadCurrent (); + if (t == NULL) + return JNI_EDETACHED; + + // FIXME: we only allow threads attached via AttachCurrentThread to + // be detached. I have no idea how we could implement detaching + // other threads, given the requirement that we must release all the + // monitors. That just seems evil. + JvAssert ((&NativeThreadClass)->isInstance (t)); + + // FIXME: release the monitors. We'll take this to mean all + // monitors acquired via the JNI interface. This means we have to + // keep track of them. + + gnu::gcj::jni::NativeThread *nt + = reinterpret_cast (t); + nt->finish (); + + return 0; +} + +static jint +_Jv_JNI_GetEnv (JavaVM *, void **penv, jint version) +{ + if (_Jv_ThreadCurrent () == NULL) + { + *penv = NULL; + return JNI_EDETACHED; + } + +#ifdef ENABLE_JVMPI + // Handle JVMPI requests. + if (version == JVMPI_VERSION_1) + { + *penv = (void *) &_Jv_JVMPI_Interface; + return 0; + } +#endif + + // FIXME: do we really want to support 1.1? + if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_1) + { + *penv = NULL; + return JNI_EVERSION; + } + + *penv = (void *) _Jv_GetCurrentJNIEnv (); + return 0; +} + +jint +JNI_GetDefaultJavaVMInitArgs (void *args) +{ + jint version = * (jint *) args; + // Here we only support 1.2. + if (version != JNI_VERSION_1_2) + return JNI_EVERSION; + + JavaVMInitArgs *ia = reinterpret_cast (args); + ia->version = JNI_VERSION_1_2; + ia->nOptions = 0; + ia->options = NULL; + ia->ignoreUnrecognized = true; + + return 0; +} + +jint +JNI_CreateJavaVM (JavaVM **vm, void **penv, void *args) +{ + JvAssert (! the_vm); + // FIXME: synchronize + JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM)); + if (nvm == NULL) + return JNI_ERR; + nvm->functions = &_Jv_JNI_InvokeFunctions; + + // Parse the arguments. + if (args != NULL) + { + jint version = * (jint *) args; + // We only support 1.2. + if (version != JNI_VERSION_1_2) + return JNI_EVERSION; + JavaVMInitArgs *ia = reinterpret_cast (args); + for (int i = 0; i < ia->nOptions; ++i) + { + if (! strcmp (ia->options[i].optionString, "vfprintf") + || ! strcmp (ia->options[i].optionString, "exit") + || ! strcmp (ia->options[i].optionString, "abort")) { - jstring str = JvNewStringUTF (_this->self->name->data); - JvThrow (new java::lang::AbstractMethodError (str)); + // We are required to recognize these, but for now we + // don't handle them in any way. FIXME. + continue; } + else if (! strncmp (ia->options[i].optionString, + "-verbose", sizeof ("-verbose") - 1)) + { + // We don't do anything with this option either. We + // might want to make sure the argument is valid, but we + // don't really care all that much for now. + continue; + } + else if (! strncmp (ia->options[i].optionString, "-D", 2)) + { + // FIXME. + continue; + } + else if (ia->ignoreUnrecognized) + { + if (ia->options[i].optionString[0] == '_' + || ! strncmp (ia->options[i].optionString, "-X", 2)) + continue; + } + + return JNI_ERR; } } - // The actual call to the JNI function. - // FIXME: if this is a static function we must include the class! - ffi_raw_call (cif, (void (*) (...)) _this->function, ret, args); + jint r =_Jv_JNI_AttachCurrentThread (nvm, penv, NULL); + if (r < 0) + return r; - do + the_vm = nvm; + *vm = the_vm; + return 0; +} + +jint +JNI_GetCreatedJavaVMs (JavaVM **vm_buffer, jsize buf_len, jsize *n_vms) +{ + if (buf_len <= 0) + return JNI_ERR; + + // We only support a single VM. + if (the_vm != NULL) + { + vm_buffer[0] = the_vm; + *n_vms = 1; + } + else + *n_vms = 0; + return 0; +} + +JavaVM * +_Jv_GetJavaVM () +{ + // FIXME: synchronize + if (! the_vm) + { + JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM)); + if (nvm != NULL) + nvm->functions = &_Jv_JNI_InvokeFunctions; + the_vm = nvm; + } + + // If this is a Java thread, we want to make sure it has an + // associated JNIEnv. + if (_Jv_ThreadCurrent () != NULL) { - _Jv_JNI_PopLocalFrame (&env, NULL); + void *ignore; + _Jv_JNI_AttachCurrentThread (the_vm, &ignore, NULL); } - while (env.locals != frame); - if (env.ex) - JvThrow (env.ex); + return the_vm; } -#endif /* INTERPRETER */ +static jint +_Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm) +{ + *vm = _Jv_GetJavaVM (); + return *vm == NULL ? JNI_ERR : JNI_OK; +} @@ -1369,242 +2085,255 @@ struct JNINativeInterface _Jv_JNIFunctions = RESERVED, RESERVED, RESERVED, - _Jv_JNI_GetVersion, - _Jv_JNI_DefineClass, - _Jv_JNI_FindClass, - _Jv_JNI_FromReflectedMethod, - _Jv_JNI_FromReflectedField, - _Jv_JNI_ToReflectedMethod, - _Jv_JNI_GetSuperclass, - _Jv_JNI_IsAssignableFrom, - _Jv_JNI_ToReflectedField, - _Jv_JNI_Throw, - _Jv_JNI_ThrowNew, - _Jv_JNI_ExceptionOccurred, - _Jv_JNI_ExceptionDescribe, - _Jv_JNI_ExceptionClear, - _Jv_JNI_FatalError, - - _Jv_JNI_PushLocalFrame, - _Jv_JNI_PopLocalFrame, - _Jv_JNI_NewGlobalRef, - _Jv_JNI_DeleteGlobalRef, - _Jv_JNI_DeleteLocalRef, - - _Jv_JNI_IsSameObject, - - _Jv_JNI_NewLocalRef, - _Jv_JNI_EnsureLocalCapacity, - - _Jv_JNI_AllocObject, - _Jv_JNI_NewObject, - _Jv_JNI_NewObjectV, - _Jv_JNI_NewObjectA, - _Jv_JNI_GetObjectClass, - _Jv_JNI_IsInstanceOf, - _Jv_JNI_GetAnyMethodID, - - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallMethod, - _Jv_JNI_CallMethodV, - _Jv_JNI_CallMethodA, - _Jv_JNI_CallVoidMethod, - _Jv_JNI_CallVoidMethodV, - _Jv_JNI_CallVoidMethodA, + _Jv_JNI_GetVersion, // GetVersion + _Jv_JNI_DefineClass, // DefineClass + _Jv_JNI_FindClass, // FindClass + _Jv_JNI_FromReflectedMethod, // FromReflectedMethod + _Jv_JNI_FromReflectedField, // FromReflectedField + _Jv_JNI_ToReflectedMethod, // ToReflectedMethod + _Jv_JNI_GetSuperclass, // GetSuperclass + _Jv_JNI_IsAssignableFrom, // IsAssignableFrom + _Jv_JNI_ToReflectedField, // ToReflectedField + _Jv_JNI_Throw, // Throw + _Jv_JNI_ThrowNew, // ThrowNew + _Jv_JNI_ExceptionOccurred, // ExceptionOccurred + _Jv_JNI_ExceptionDescribe, // ExceptionDescribe + _Jv_JNI_ExceptionClear, // ExceptionClear + _Jv_JNI_FatalError, // FatalError + + _Jv_JNI_PushLocalFrame, // PushLocalFrame + _Jv_JNI_PopLocalFrame, // PopLocalFrame + _Jv_JNI_NewGlobalRef, // NewGlobalRef + _Jv_JNI_DeleteGlobalRef, // DeleteGlobalRef + _Jv_JNI_DeleteLocalRef, // DeleteLocalRef + + _Jv_JNI_IsSameObject, // IsSameObject + + _Jv_JNI_NewLocalRef, // NewLocalRef + _Jv_JNI_EnsureLocalCapacity, // EnsureLocalCapacity + + _Jv_JNI_AllocObject, // AllocObject + _Jv_JNI_NewObject, // NewObject + _Jv_JNI_NewObjectV, // NewObjectV + _Jv_JNI_NewObjectA, // NewObjectA + _Jv_JNI_GetObjectClass, // GetObjectClass + _Jv_JNI_IsInstanceOf, // IsInstanceOf + _Jv_JNI_GetAnyMethodID, // GetMethodID + + _Jv_JNI_CallMethod, // CallObjectMethod + _Jv_JNI_CallMethodV, // CallObjectMethodV + _Jv_JNI_CallMethodA, // CallObjectMethodA + _Jv_JNI_CallMethod, // CallBooleanMethod + _Jv_JNI_CallMethodV, // CallBooleanMethodV + _Jv_JNI_CallMethodA, // CallBooleanMethodA + _Jv_JNI_CallMethod, // CallByteMethod + _Jv_JNI_CallMethodV, // CallByteMethodV + _Jv_JNI_CallMethodA, // CallByteMethodA + _Jv_JNI_CallMethod, // CallCharMethod + _Jv_JNI_CallMethodV, // CallCharMethodV + _Jv_JNI_CallMethodA, // CallCharMethodA + _Jv_JNI_CallMethod, // CallShortMethod + _Jv_JNI_CallMethodV, // CallShortMethodV + _Jv_JNI_CallMethodA, // CallShortMethodA + _Jv_JNI_CallMethod, // CallIntMethod + _Jv_JNI_CallMethodV, // CallIntMethodV + _Jv_JNI_CallMethodA, // CallIntMethodA + _Jv_JNI_CallMethod, // CallLongMethod + _Jv_JNI_CallMethodV, // CallLongMethodV + _Jv_JNI_CallMethodA, // CallLongMethodA + _Jv_JNI_CallMethod, // CallFloatMethod + _Jv_JNI_CallMethodV, // CallFloatMethodV + _Jv_JNI_CallMethodA, // CallFloatMethodA + _Jv_JNI_CallMethod, // CallDoubleMethod + _Jv_JNI_CallMethodV, // CallDoubleMethodV + _Jv_JNI_CallMethodA, // CallDoubleMethodA + _Jv_JNI_CallVoidMethod, // CallVoidMethod + _Jv_JNI_CallVoidMethodV, // CallVoidMethodV + _Jv_JNI_CallVoidMethodA, // CallVoidMethodA // Nonvirtual method invocation functions follow. - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyMethod, - _Jv_JNI_CallAnyMethodV, - _Jv_JNI_CallAnyMethodA, - _Jv_JNI_CallAnyVoidMethod, - _Jv_JNI_CallAnyVoidMethodV, - _Jv_JNI_CallAnyVoidMethodA, - - _Jv_JNI_GetAnyFieldID, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_GetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_SetField, - _Jv_JNI_GetAnyMethodID, - - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticMethod, - _Jv_JNI_CallStaticMethodV, - _Jv_JNI_CallStaticMethodA, - _Jv_JNI_CallStaticVoidMethod, - _Jv_JNI_CallStaticVoidMethodV, - _Jv_JNI_CallStaticVoidMethodA, - - _Jv_JNI_GetAnyFieldID, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_GetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_SetStaticField, - _Jv_JNI_NewString, - _Jv_JNI_GetStringLength, - _Jv_JNI_GetStringChars, - _Jv_JNI_ReleaseStringChars, - _Jv_JNI_NewStringUTF, - _Jv_JNI_GetStringUTFLength, - _Jv_JNI_GetStringUTFChars, - _Jv_JNI_ReleaseStringUTFChars, - _Jv_JNI_GetArrayLength, - _Jv_JNI_NewObjectArray, - _Jv_JNI_GetObjectArrayElement, - _Jv_JNI_SetObjectArrayElement, + _Jv_JNI_CallAnyMethod, // CallNonvirtualObjectMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualObjectMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualObjectMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualBooleanMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualBooleanMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualBooleanMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualByteMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualByteMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualByteMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualCharMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualCharMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualCharMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualShortMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualShortMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualShortMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualIntMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualIntMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualIntMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualLongMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualLongMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualLongMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualFloatMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualFloatMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualFloatMethodA + _Jv_JNI_CallAnyMethod, // CallNonvirtualDoubleMethod + _Jv_JNI_CallAnyMethodV, // CallNonvirtualDoubleMethodV + _Jv_JNI_CallAnyMethodA, // CallNonvirtualDoubleMethodA + _Jv_JNI_CallAnyVoidMethod, // CallNonvirtualVoidMethod + _Jv_JNI_CallAnyVoidMethodV, // CallNonvirtualVoidMethodV + _Jv_JNI_CallAnyVoidMethodA, // CallNonvirtualVoidMethodA + + _Jv_JNI_GetAnyFieldID, // GetFieldID + _Jv_JNI_GetField, // GetObjectField + _Jv_JNI_GetField, // GetBooleanField + _Jv_JNI_GetField, // GetByteField + _Jv_JNI_GetField, // GetCharField + _Jv_JNI_GetField, // GetShortField + _Jv_JNI_GetField, // GetIntField + _Jv_JNI_GetField, // GetLongField + _Jv_JNI_GetField, // GetFloatField + _Jv_JNI_GetField, // GetDoubleField + _Jv_JNI_SetField, // SetObjectField + _Jv_JNI_SetField, // SetBooleanField + _Jv_JNI_SetField, // SetByteField + _Jv_JNI_SetField, // SetCharField + _Jv_JNI_SetField, // SetShortField + _Jv_JNI_SetField, // SetIntField + _Jv_JNI_SetField, // SetLongField + _Jv_JNI_SetField, // SetFloatField + _Jv_JNI_SetField, // SetDoubleField + _Jv_JNI_GetAnyMethodID, // GetStaticMethodID + + _Jv_JNI_CallStaticMethod, // CallStaticObjectMethod + _Jv_JNI_CallStaticMethodV, // CallStaticObjectMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticObjectMethodA + _Jv_JNI_CallStaticMethod, // CallStaticBooleanMethod + _Jv_JNI_CallStaticMethodV, // CallStaticBooleanMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticBooleanMethodA + _Jv_JNI_CallStaticMethod, // CallStaticByteMethod + _Jv_JNI_CallStaticMethodV, // CallStaticByteMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticByteMethodA + _Jv_JNI_CallStaticMethod, // CallStaticCharMethod + _Jv_JNI_CallStaticMethodV, // CallStaticCharMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticCharMethodA + _Jv_JNI_CallStaticMethod, // CallStaticShortMethod + _Jv_JNI_CallStaticMethodV, // CallStaticShortMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticShortMethodA + _Jv_JNI_CallStaticMethod, // CallStaticIntMethod + _Jv_JNI_CallStaticMethodV, // CallStaticIntMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticIntMethodA + _Jv_JNI_CallStaticMethod, // CallStaticLongMethod + _Jv_JNI_CallStaticMethodV, // CallStaticLongMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticLongMethodA + _Jv_JNI_CallStaticMethod, // CallStaticFloatMethod + _Jv_JNI_CallStaticMethodV, // CallStaticFloatMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticFloatMethodA + _Jv_JNI_CallStaticMethod, // CallStaticDoubleMethod + _Jv_JNI_CallStaticMethodV, // CallStaticDoubleMethodV + _Jv_JNI_CallStaticMethodA, // CallStaticDoubleMethodA + _Jv_JNI_CallStaticVoidMethod, // CallStaticVoidMethod + _Jv_JNI_CallStaticVoidMethodV, // CallStaticVoidMethodV + _Jv_JNI_CallStaticVoidMethodA, // CallStaticVoidMethodA + + _Jv_JNI_GetAnyFieldID, // GetStaticFieldID + _Jv_JNI_GetStaticField, // GetStaticObjectField + _Jv_JNI_GetStaticField, // GetStaticBooleanField + _Jv_JNI_GetStaticField, // GetStaticByteField + _Jv_JNI_GetStaticField, // GetStaticCharField + _Jv_JNI_GetStaticField, // GetStaticShortField + _Jv_JNI_GetStaticField, // GetStaticIntField + _Jv_JNI_GetStaticField, // GetStaticLongField + _Jv_JNI_GetStaticField, // GetStaticFloatField + _Jv_JNI_GetStaticField, // GetStaticDoubleField + _Jv_JNI_SetStaticField, // SetStaticObjectField + _Jv_JNI_SetStaticField, // SetStaticBooleanField + _Jv_JNI_SetStaticField, // SetStaticByteField + _Jv_JNI_SetStaticField, // SetStaticCharField + _Jv_JNI_SetStaticField, // SetStaticShortField + _Jv_JNI_SetStaticField, // SetStaticIntField + _Jv_JNI_SetStaticField, // SetStaticLongField + _Jv_JNI_SetStaticField, // SetStaticFloatField + _Jv_JNI_SetStaticField, // SetStaticDoubleField + _Jv_JNI_NewString, // NewString + _Jv_JNI_GetStringLength, // GetStringLength + _Jv_JNI_GetStringChars, // GetStringChars + _Jv_JNI_ReleaseStringChars, // ReleaseStringChars + _Jv_JNI_NewStringUTF, // NewStringUTF + _Jv_JNI_GetStringUTFLength, // GetStringUTFLength + _Jv_JNI_GetStringUTFChars, // GetStringUTFLength + _Jv_JNI_ReleaseStringUTFChars, // ReleaseStringUTFChars + _Jv_JNI_GetArrayLength, // GetArrayLength + _Jv_JNI_NewObjectArray, // NewObjectArray + _Jv_JNI_GetObjectArrayElement, // GetObjectArrayElement + _Jv_JNI_SetObjectArrayElement, // SetObjectArrayElement _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_NewPrimitiveArray, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_ReleasePrimitiveArrayElements, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_GetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - _Jv_JNI_SetPrimitiveArrayRegion, - NOT_IMPL /* RegisterNatives */, - NOT_IMPL /* UnregisterNatives */, - _Jv_JNI_MonitorEnter, - _Jv_JNI_MonitorExit, - NOT_IMPL /* GetJavaVM */, - - _Jv_JNI_GetStringRegion, - _Jv_JNI_GetStringUTFRegion, - _Jv_JNI_GetPrimitiveArrayCritical, - _Jv_JNI_ReleasePrimitiveArrayCritical, - _Jv_JNI_GetStringCritical, - _Jv_JNI_ReleaseStringCritical, + // NewBooleanArray + _Jv_JNI_NewPrimitiveArray, // NewByteArray + _Jv_JNI_NewPrimitiveArray, // NewCharArray + _Jv_JNI_NewPrimitiveArray, // NewShortArray + _Jv_JNI_NewPrimitiveArray, // NewIntArray + _Jv_JNI_NewPrimitiveArray, // NewLongArray + _Jv_JNI_NewPrimitiveArray, // NewFloatArray + _Jv_JNI_NewPrimitiveArray, // NewDoubleArray + _Jv_JNI_GetPrimitiveArrayElements, // GetBooleanArrayElements + _Jv_JNI_GetPrimitiveArrayElements, // GetByteArrayElements + _Jv_JNI_GetPrimitiveArrayElements, // GetCharArrayElements + _Jv_JNI_GetPrimitiveArrayElements, // GetShortArrayElements + _Jv_JNI_GetPrimitiveArrayElements, // GetIntArrayElements + _Jv_JNI_GetPrimitiveArrayElements, // GetLongArrayElements + _Jv_JNI_GetPrimitiveArrayElements, // GetFloatArrayElements + _Jv_JNI_GetPrimitiveArrayElements, // GetDoubleArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseBooleanArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseByteArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseCharArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseShortArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseIntArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseLongArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseFloatArrayElements + _Jv_JNI_ReleasePrimitiveArrayElements, // ReleaseDoubleArrayElements + _Jv_JNI_GetPrimitiveArrayRegion, // GetBooleanArrayRegion + _Jv_JNI_GetPrimitiveArrayRegion, // GetByteArrayRegion + _Jv_JNI_GetPrimitiveArrayRegion, // GetCharArrayRegion + _Jv_JNI_GetPrimitiveArrayRegion, // GetShortArrayRegion + _Jv_JNI_GetPrimitiveArrayRegion, // GetIntArrayRegion + _Jv_JNI_GetPrimitiveArrayRegion, // GetLongArrayRegion + _Jv_JNI_GetPrimitiveArrayRegion, // GetFloatArrayRegion + _Jv_JNI_GetPrimitiveArrayRegion, // GetDoubleArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetBooleanArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetByteArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetCharArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetShortArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetIntArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetLongArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetFloatArrayRegion + _Jv_JNI_SetPrimitiveArrayRegion, // SetDoubleArrayRegion + _Jv_JNI_RegisterNatives, // RegisterNatives + _Jv_JNI_UnregisterNatives, // UnregisterNatives + _Jv_JNI_MonitorEnter, // MonitorEnter + _Jv_JNI_MonitorExit, // MonitorExit + _Jv_JNI_GetJavaVM, // GetJavaVM + + _Jv_JNI_GetStringRegion, // GetStringRegion + _Jv_JNI_GetStringUTFRegion, // GetStringUTFRegion + _Jv_JNI_GetPrimitiveArrayCritical, // GetPrimitiveArrayCritical + _Jv_JNI_ReleasePrimitiveArrayCritical, // ReleasePrimitiveArrayCritical + _Jv_JNI_GetStringCritical, // GetStringCritical + _Jv_JNI_ReleaseStringCritical, // ReleaseStringCritical NOT_IMPL /* newweakglobalref */, NOT_IMPL /* deleteweakglobalref */, _Jv_JNI_ExceptionCheck }; + +struct JNIInvokeInterface _Jv_JNI_InvokeFunctions = +{ + RESERVED, + RESERVED, + RESERVED, + + _Jv_JNI_DestroyJavaVM, + _Jv_JNI_AttachCurrentThread, + _Jv_JNI_DetachCurrentThread, + _Jv_JNI_GetEnv +};