summaryrefslogtreecommitdiff
path: root/libjava/jni.cc
diff options
context:
space:
mode:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2000-02-10 20:31:48 +0000
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>2000-02-10 20:31:48 +0000
commitbf1967d63c238862df52d7823dbfd4abc9d5c647 (patch)
tree893852baae8ef6aa653f36d94ed11d6728aa30ea /libjava/jni.cc
parent083909e35fea95ba09493d725327722f279eaf14 (diff)
downloadgcc-bf1967d63c238862df52d7823dbfd4abc9d5c647.tar.gz
* gnu/gcj/jni/natNativeThread.cc: New file.
* gnu/gcj/jni/NativeThread.java: New file. * java/lang/Thread.java (data): Now a RawData. * include/jvm.h (_Jv_GetCurrentJNIEnv, _Jv_SetCurrentJNIEnv): Declare. * Makefile.in: Rebuilt. * Makefile.am (java/lang/Thread.h): New target. (ordinary_java_source_files): Added NativeThread.java. (nat_source_files): Added natNativeThread.cc. * java/lang/natThread.cc: Include <jni.h> (struct natThread): Added `jni_env' field. (_Jv_GetCurrentJNIEnv): New function. (_Jv_SetCurrentJNIEnv): Likewise. (initialize_native): Initialize jni_env. Include RawData.h. * jni.cc (ThreadGroupClass): New define. (_Jv_JNI_InvokeFunctions): New structure. (JNI_GetCreatedJavaVMs): New function. (the_vm): New global. (JNI_GetDefaultJavaVMInitArgs): New function. Include NativeThread.h. (NativeThreadClass): New define. (_Jv_JNI_EnsureLocalCapacity): Return JNI_ERR, not -1. (_Jv_JNI_DestroyJavaVM): New function. (_Jv_JNI_AttachCurrentThread): New function. (_Jv_JNI_DetachCurrentThread): New function. (_Jv_JNI_GetEnv): New function. (JNI_CreateJavaVM): New function. (_Jv_JNI_GetJavaVM): New function. (_Jv_JNIFunctions): Added entry for GetJavaVM. * include/jni.h (JavaVMAttachArgs): New structure. (JNI_EDETACHED): New define. (JNI_EVERSION): Likewise. (JavaVM): Define properly. (struct JNIInvokeInterface): New structure. (class _Jv_JavaVM): New class. (JNI_OnLoad, JNI_OnUnload): Declare. (JNI_GetDefaultJavaVMInitArgs, JNI_CreateJavaVM, JNI_GetCreatedJavaVMs): Declare. (JavaVMInitArgs): New typedef. (JavaVMOption): Likewise. (JNI_ERR): New define. (JNI_OK): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@31901 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/jni.cc')
-rw-r--r--libjava/jni.cc259
1 files changed, 256 insertions, 3 deletions
diff --git a/libjava/jni.cc b/libjava/jni.cc
index b6728e5ab86..6beb6f7f8a4 100644
--- a/libjava/jni.cc
+++ b/libjava/jni.cc
@@ -36,6 +36,7 @@ details. */
#include <java/lang/OutOfMemoryError.h>
#include <java/util/Hashtable.h>
#include <java/lang/Integer.h>
+#include <gnu/gcj/jni/NativeThread.h>
#include <gcj/method.h>
#include <gcj/field.h>
@@ -51,6 +52,10 @@ extern java::lang::Class ObjectClass;
extern java::lang::Class ThrowableClass;
#define MethodClass _CL_Q44java4lang7reflect6Method
extern java::lang::Class MethodClass;
+#define ThreadGroupClass _CL_Q34java4lang11ThreadGroup
+extern java::lang::Class ThreadGroupClass;
+#define NativeThreadClass _CL_Q43gnu3gcj3jni12NativeThread
+extern java::lang::Class ThreadGroupClass;
// This enum is used to select different template instantiations in
// the invocation code.
@@ -62,8 +67,9 @@ 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.
@@ -89,6 +95,9 @@ 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;
+
void
@@ -178,7 +187,7 @@ _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
{
// FIXME: exception processing.
env->ex = new java::lang::OutOfMemoryError;
- return -1;
+ return JNI_ERR;
}
frame->marker = true;
@@ -1380,6 +1389,238 @@ _Jv_JNIMethod::call (ffi_cif *cif, void *ret, ffi_raw *args, void *__this)
+//
+// Invocation API.
+//
+
+// An internal helper function.
+static jint
+_Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv, void *args)
+{
+ JavaVMAttachArgs *attach = reinterpret_cast<JavaVMAttachArgs *> (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<java::lang::ThreadGroup *> (attach->group);
+ }
+
+ // Attaching an already-attached thread is a no-op.
+ if (_Jv_ThreadCurrent () != NULL)
+ return 0;
+
+ // FIXME: NULL return?
+ JNIEnv *env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
+ env->p = &_Jv_JNIFunctions;
+ env->ex = NULL;
+ env->klass = NULL;
+ // FIXME: NULL return?
+ env->locals
+ = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
+ + (FRAME_SIZE
+ * sizeof (jobject)));
+ *penv = reinterpret_cast<void *> (env);
+
+ java::lang::Thread *t = new gnu::gcj::jni::NativeThread (group, name);
+ t = t; // Avoid compiler warning. Eww.
+ _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)
+ {
+ jint r = _Jv_JNI_AttachCurrentThread (vm,
+ JvNewStringLatin1 ("main"),
+ reinterpret_cast<void **> (&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<gnu::gcj::jni::NativeThread *> (t);
+ nt->finish ();
+
+ return 0;
+}
+
+static jint
+_Jv_JNI_GetEnv (JavaVM *, void **penv, jint version)
+{
+ if (_Jv_ThreadCurrent () == NULL)
+ {
+ *penv = NULL;
+ return JNI_EDETACHED;
+ }
+
+ // 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<JavaVMInitArgs *> (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<JavaVMInitArgs *> (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"))
+ {
+ // 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;
+ }
+ }
+
+ jint r =_Jv_JNI_AttachCurrentThread (nvm, penv, NULL);
+ if (r < 0)
+ return r;
+
+ the_vm = nvm;
+ *vm = the_vm;
+ return 0;
+}
+
+jint
+JNI_GetCreatedJavaVMs (JavaVM **vm_buffer, jsize buf_len, jsize *n_vms)
+{
+ JvAssert (buf_len > 0);
+ // We only support a single VM.
+ if (the_vm != NULL)
+ {
+ vm_buffer[0] = the_vm;
+ *n_vms = 1;
+ }
+ else
+ *n_vms = 0;
+ return 0;
+}
+
+jint
+_Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm)
+{
+ // FIXME: synchronize
+ if (! the_vm)
+ {
+ JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
+ if (nvm == NULL)
+ return JNI_ERR;
+ nvm->functions = &_Jv_JNI_InvokeFunctions;
+ the_vm = nvm;
+ }
+
+ *vm = the_vm;
+ return 0;
+}
+
+
+
#define NOT_IMPL NULL
#define RESERVED NULL
@@ -1614,7 +1855,7 @@ struct JNINativeInterface _Jv_JNIFunctions =
NOT_IMPL /* UnregisterNatives */,
_Jv_JNI_MonitorEnter,
_Jv_JNI_MonitorExit,
- NOT_IMPL /* GetJavaVM */,
+ _Jv_JNI_GetJavaVM,
_Jv_JNI_GetStringRegion,
_Jv_JNI_GetStringUTFRegion,
@@ -1628,3 +1869,15 @@ struct JNINativeInterface _Jv_JNIFunctions =
_Jv_JNI_ExceptionCheck
};
+
+struct JNIInvokeInterface _Jv_JNI_InvokeFunctions =
+{
+ RESERVED,
+ RESERVED,
+ RESERVED,
+
+ _Jv_JNI_DestroyJavaVM,
+ _Jv_JNI_AttachCurrentThread,
+ _Jv_JNI_DetachCurrentThread,
+ _Jv_JNI_GetEnv
+};