natNativeThread.cc: New file.

* 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.

From-SVN: r31901
This commit is contained in:
Tom Tromey 2000-02-10 20:31:48 +00:00 committed by Tom Tromey
parent ef86eabb6c
commit aaf0766e9f
10 changed files with 560 additions and 30 deletions

View file

@ -1,3 +1,49 @@
2000-02-10 Tom Tromey <tromey@cygnus.com>
* 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.
2000-02-10 Andrew Haley <aph@cygnus.com>
* interpret.cc: Don't include fdlibm.h.

View file

@ -221,6 +221,16 @@ java/lang/FirstThread.h: java/lang/FirstThread.class libgcj.zip
-friend 'void _Jv_RunMain (const char*, int, const char **);' \
$(basename $<)
java/lang/Thread.h: java/lang/Thread.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-prepend 'class _Jv_JNIEnv;' \
## Eww.
-prepend 'extern "Java" { namespace gnu { namespace gcj { namespace jni { class NativeThread; } } } };' \
-friend '_Jv_JNIEnv * _Jv_GetCurrentJNIEnv ();' \
-friend 'void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *env);' \
-friend 'class gnu::gcj::jni::NativeThread;' \
$(basename $<)
java/lang/String.h: java/lang/String.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-friend 'jchar* _Jv_GetStringChars (jstring str);' \
@ -512,6 +522,7 @@ built_java_source_files = java/lang/ConcreteProcess.java
## convert_source_files. If the .java file has a hand-maintained
## header, please list it in special_java_source_files.
ordinary_java_source_files = $(convert_source_files) \
gnu/gcj/jni/NativeThread.java \
gnu/gcj/runtime/MethodInvocation.java \
gnu/gcj/runtime/VMClassLoader.java \
gnu/gcj/text/BaseBreakIterator.java \
@ -796,6 +807,7 @@ gnu/gcj/convert/natInput_EUCJIS.cc \
gnu/gcj/convert/natInput_SJIS.cc \
gnu/gcj/convert/natOutput_EUCJIS.cc \
gnu/gcj/convert/natOutput_SJIS.cc \
gnu/gcj/jni/natNativeThread.cc \
java/io/natFile.cc \
java/io/natFileDescriptor.cc \
java/lang/natCharacter.cc \

View file

@ -326,6 +326,7 @@ java/awt/peer/WindowPeer.java
built_java_source_files = java/lang/ConcreteProcess.java
ordinary_java_source_files = $(convert_source_files) \
gnu/gcj/jni/NativeThread.java \
gnu/gcj/runtime/MethodInvocation.java \
gnu/gcj/runtime/VMClassLoader.java \
gnu/gcj/text/BaseBreakIterator.java \
@ -610,6 +611,7 @@ gnu/gcj/convert/natInput_EUCJIS.cc \
gnu/gcj/convert/natInput_SJIS.cc \
gnu/gcj/convert/natOutput_EUCJIS.cc \
gnu/gcj/convert/natOutput_SJIS.cc \
gnu/gcj/jni/natNativeThread.cc \
java/io/natFile.cc \
java/io/natFileDescriptor.cc \
java/lang/natCharacter.cc \
@ -730,7 +732,8 @@ LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DATA = $(data_DATA) $(toolexeclib_DATA)
DIST_COMMON = README COPYING.LIB ChangeLog Makefile.am Makefile.in NEWS \
THANKS acinclude.m4 aclocal.m4 configure configure.in libgcj.spec.in
THANKS acconfig.h acinclude.m4 aclocal.m4 configure configure.in \
include/config.h.in include/stamp-h.in libgcj.spec.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
@ -752,8 +755,8 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/gnu/gcj/convert/Output_JavaSrc.P \
.deps/gnu/gcj/convert/Output_SJIS.P .deps/gnu/gcj/convert/Output_UTF8.P \
.deps/gnu/gcj/convert/Output_iconv.P \
.deps/gnu/gcj/convert/UnicodeToBytes.P .deps/gnu/gcj/math/MPN.P \
.deps/gnu/gcj/protocol/file/Connection.P \
.deps/gnu/gcj/convert/UnicodeToBytes.P .deps/gnu/gcj/jni/NativeThread.P \
.deps/gnu/gcj/math/MPN.P .deps/gnu/gcj/protocol/file/Connection.P \
.deps/gnu/gcj/protocol/file/Handler.P \
.deps/gnu/gcj/protocol/http/Connection.P \
.deps/gnu/gcj/protocol/http/Handler.P \
@ -955,6 +958,34 @@ config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
include/config.h: include/stamp-h
@if test ! -f $@; then \
rm -f include/stamp-h; \
$(MAKE) include/stamp-h; \
else :; fi
include/stamp-h: $(srcdir)/include/config.h.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES= CONFIG_HEADERS=include/config.h \
$(SHELL) ./config.status
@echo timestamp > include/stamp-h 2> /dev/null
$(srcdir)/include/config.h.in: @MAINTAINER_MODE_TRUE@$(srcdir)/include/stamp-h.in
@if test ! -f $@; then \
rm -f $(srcdir)/include/stamp-h.in; \
$(MAKE) $(srcdir)/include/stamp-h.in; \
else :; fi
$(srcdir)/include/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
cd $(top_srcdir) && $(AUTOHEADER)
@echo timestamp > $(srcdir)/include/stamp-h.in 2> /dev/null
mostlyclean-hdr:
clean-hdr:
distclean-hdr:
-rm -f include/config.h
maintainer-clean-hdr:
libgcj.spec: $(top_builddir)/config.status libgcj.spec.in
cd $(top_builddir) && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
@ -1393,31 +1424,33 @@ distclean-generic:
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-toolexeclibLIBRARIES mostlyclean-compile \
mostlyclean-libtool mostlyclean-toolexeclibLTLIBRARIES \
mostlyclean-am: mostlyclean-hdr mostlyclean-toolexeclibLIBRARIES \
mostlyclean-compile mostlyclean-libtool \
mostlyclean-toolexeclibLTLIBRARIES \
mostlyclean-binPROGRAMS mostlyclean-noinstPROGRAMS \
mostlyclean-tags mostlyclean-depend mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-toolexeclibLIBRARIES clean-compile clean-libtool \
clean-toolexeclibLTLIBRARIES clean-binPROGRAMS \
clean-noinstPROGRAMS clean-tags clean-depend \
clean-generic mostlyclean-am clean-local
clean-am: clean-hdr clean-toolexeclibLIBRARIES clean-compile \
clean-libtool clean-toolexeclibLTLIBRARIES \
clean-binPROGRAMS clean-noinstPROGRAMS clean-tags \
clean-depend clean-generic mostlyclean-am clean-local
clean: clean-recursive
distclean-am: distclean-toolexeclibLIBRARIES distclean-compile \
distclean-libtool distclean-toolexeclibLTLIBRARIES \
distclean-binPROGRAMS distclean-noinstPROGRAMS \
distclean-tags distclean-depend distclean-generic \
clean-am
distclean-am: distclean-hdr distclean-toolexeclibLIBRARIES \
distclean-compile distclean-libtool \
distclean-toolexeclibLTLIBRARIES distclean-binPROGRAMS \
distclean-noinstPROGRAMS distclean-tags \
distclean-depend distclean-generic clean-am
-rm -f libtool
distclean: distclean-recursive
-rm -f config.status
maintainer-clean-am: maintainer-clean-toolexeclibLIBRARIES \
maintainer-clean-am: maintainer-clean-hdr \
maintainer-clean-toolexeclibLIBRARIES \
maintainer-clean-compile maintainer-clean-libtool \
maintainer-clean-toolexeclibLTLIBRARIES \
maintainer-clean-binPROGRAMS \
@ -1430,7 +1463,8 @@ maintainer-clean-am: maintainer-clean-toolexeclibLIBRARIES \
maintainer-clean: maintainer-clean-recursive
-rm -f config.status
.PHONY: mostlyclean-toolexeclibLIBRARIES distclean-toolexeclibLIBRARIES \
.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
mostlyclean-toolexeclibLIBRARIES distclean-toolexeclibLIBRARIES \
clean-toolexeclibLIBRARIES maintainer-clean-toolexeclibLIBRARIES \
uninstall-toolexeclibLIBRARIES install-toolexeclibLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
@ -1514,6 +1548,15 @@ java/lang/FirstThread.h: java/lang/FirstThread.class libgcj.zip
-friend 'void _Jv_RunMain (const char*, int, const char **);' \
$(basename $<)
java/lang/Thread.h: java/lang/Thread.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-prepend 'class _Jv_JNIEnv;' \
-prepend 'extern "Java" { namespace gnu { namespace gcj { namespace jni { class NativeThread; } } } };' \
-friend '_Jv_JNIEnv * _Jv_GetCurrentJNIEnv ();' \
-friend 'void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *env);' \
-friend 'class gnu::gcj::jni::NativeThread;' \
$(basename $<)
java/lang/String.h: java/lang/String.class libgcj.zip
$(GCJH) -classpath $(top_builddir) \
-friend 'jchar* _Jv_GetStringChars (jstring str);' \

View file

@ -0,0 +1,28 @@
// NativeThread.java - Wrapper for attached user threads.
/* Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package gnu.gcj.jni;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date February 9, 2000
*/
public class NativeThread extends Thread
{
public NativeThread (ThreadGroup g, String name)
{
super (g, null, name);
alive_flag = true;
}
// Call this to mark the thread as finished.
public native void finish ();
}

View file

@ -0,0 +1,24 @@
// natNativeThread.cc - Native side of attached threads.
/* Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
// Written by Tom Tromey <tromey@cygnus.com>
#include <config.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <gnu/gcj/jni/NativeThread.h>
#include <java/lang/Thread.h>
void
gnu::gcj::jni::NativeThread::finish ()
{
finish_ ();
}

View file

@ -23,6 +23,7 @@ details. */
#include <gcj/javaprims.h>
typedef struct _Jv_JNIEnv JNIEnv;
typedef struct _Jv_JavaVM JavaVM;
#define JNI_TRUE true
#define JNI_FALSE false
@ -59,6 +60,7 @@ typedef void *jfieldID;
typedef void *jmethodID;
typedef const struct JNINativeInterface *JNIEnv;
typedef const struct JNIInvokeInterface *JavaVM;
#define JNI_TRUE 1
#define JNI_TRUE 0
@ -76,6 +78,32 @@ typedef jobject jweak;
#define JNI_COMMIT 1
#define JNI_ABORT 2
/* Error codes */
#define JNI_OK 0
#define JNI_ERR -1
#define JNI_EDETACHED -2
#define JNI_EVERSION -3
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* These functions might be defined in libraries which we load; the
JNI implementation calls them at the appropriate times. */
extern jint JNI_OnLoad (JavaVM *, void *);
extern void JNI_OnUnload (JavaVM *, void *);
/* These functions are called by user code to start using the
invocation API. */
extern jint JNI_GetDefaultJavaVMInitArgs (void *);
extern jint JNI_CreateJavaVM (JavaVM **, void **, void *);
extern jint JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
#ifdef __cplusplus
};
#endif /* __cplusplus */
typedef union jvalue
{
jboolean z;
@ -99,9 +127,6 @@ typedef struct
void *fnPtr; /* Sigh. */
} JNINativeMethod;
/* FIXME: this is just a placeholder. */
typedef int JavaVM;
struct JNINativeInterface
{
_Jv_func reserved0;
@ -1402,4 +1427,74 @@ public:
};
#endif /* __cplusplus */
/*
* Invocation API.
*/
struct JNIInvokeInterface
{
_Jv_func reserved0;
_Jv_func reserved1;
_Jv_func reserved2;
jint (*DestroyJavaVM) (JavaVM *);
jint (*AttachCurrentThread) (JavaVM *, void **, void *);
jint (*DetachCurrentThread) (JavaVM *);
jint (*GetEnv) (JavaVM *, void **, jint);
};
#ifdef __cplusplus
class _Jv_JavaVM
{
public:
const struct JNIInvokeInterface *functions;
private:
/* FIXME: other fields. */
public:
jint DestroyJavaVM ()
{ return functions->DestroyJavaVM (this); }
jint AttachCurrentThread (void **penv, void *args)
{ return functions->AttachCurrentThread (this, penv, args); }
jint DetachCurrentThread ()
{ return functions->DetachCurrentThread (this); }
jint GetEnv (void **penv, jint version)
{ return functions->GetEnv (this, penv, version); }
};
#endif /* __cplusplus */
typedef struct JavaVMAttachArgs
{
jint version; /* Must be JNI_VERSION_1_2. */
char *name; /* The name of the thread (or NULL). */
jobject group; /* Global ref of a ThreadGroup object
(or NULL). */
} JavaVMAttachArgs;
typedef struct JavaVMOption
{
char *optionString;
void *extraInfo;
} JavaVMOption;
typedef struct JavaVMInitArgs
{
/* Must be JNI_VERSION_1_2. */
jint version;
/* Number of options. */
jint nOptions;
/* Options to the VM. */
JavaVMOption *options;
/* Whether we should ignore unrecognized options. */
jboolean ignoreUnrecognized;
} JavaVMInitArgs;
#endif /* __GCJ_JNI_H__ */

View file

@ -207,4 +207,8 @@ void *_Jv_FindSymbolInExecutable (const char *);
/* Initialize JNI. */
extern void _Jv_JNI_Init (void);
/* Get or set the per-thread JNIEnv used by the invocation API. */
_Jv_JNIEnv *_Jv_GetCurrentJNIEnv ();
void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *);
#endif /* __JAVA_JVM_H__ */

View file

@ -1,6 +1,6 @@
// Thread.java - Thread class.
/* Copyright (C) 1998, 1999 Red Hat, Inc.
/* Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
This file is part of libgcj.
@ -10,6 +10,8 @@ details. */
package java.lang;
import gnu.gcj.RawData;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date August 24, 1998
@ -297,11 +299,8 @@ public class Thread implements Runnable
private boolean interrupt_flag;
private boolean alive_flag;
// This is a bit odd. We need a way to represent some data that is
// manipulated only by the native side of this class. We represent
// it as a Java object reference. However, it is not actually a
// Java object.
private Object data;
// Our native data.
private RawData data;
// Next thread number to assign.
private static int nextThreadNumber = 0;

View file

@ -1,6 +1,6 @@
// natThread.cc - Native part of Thread class.
/* Copyright (C) 1998, 1999 Red Hat, Inc.
/* Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
This file is part of libgcj.
@ -23,6 +23,9 @@ details. */
#include <java/lang/IllegalThreadStateException.h>
#include <java/lang/InterruptedException.h>
#include <java/lang/NullPointerException.h>
#include <gnu/gcj/RawData.h>
#include <jni.h>
@ -40,6 +43,9 @@ struct natThread
// This is private data for the thread system layer.
_Jv_Thread_t *thread;
// Each thread has its own JNI object.
JNIEnv *jni_env;
// All threads waiting to join this thread are linked together and
// waiting on their respective `interrupt' condition variables.
// When this thread exits, it notifies each such thread by
@ -83,10 +89,13 @@ java::lang::Thread::initialize_native (void)
// own finalizer then we will need to reinitialize this structure at
// any "interesting" point.
natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
data = (jobject) nt;
data = reinterpret_cast<gnu::gcj::RawData *> (nt);
_Jv_MutexInit (&nt->interrupt_mutex);
_Jv_CondInit (&nt->interrupt_cond);
_Jv_ThreadInitData (&nt->thread, this);
// FIXME: if JNI_ENV is set we will want to free it. It is
// malloc()d.
nt->jni_env = NULL;
nt->joiner = 0;
nt->next = 0;
}
@ -324,3 +333,20 @@ java::lang::Thread::yield (void)
{
_Jv_ThreadYield ();
}
JNIEnv *
_Jv_GetCurrentJNIEnv ()
{
java::lang::Thread *t = _Jv_ThreadCurrent ();
if (t == NULL)
return NULL;
return ((natThread *) t->data)->jni_env;
}
void
_Jv_SetCurrentJNIEnv (JNIEnv *env)
{
java::lang::Thread *t = _Jv_ThreadCurrent ();
JvAssert (t != NULL);
((natThread *) t->data)->jni_env = env;
}

View file

@ -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
};