Patch: JNI

Tom Tromey tromey@cygnus.com
Fri Jan 21 15:49:00 GMT 2000


I'm committing the appended patch.  This patch implements a large
chunk of JNI.  JNI still doesn't work, but this is a step in that
direction.

2000-01-21  Tom Tromey  <tromey@cygnus.com>

	* java/lang/reflect/natConstructor.cc (newInstance): Use
	_Jv_CallAnyMethodA.
	* include/jvm.h: Declare _Jv_CallAnyMethodA.
	* java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA): Renamed
	from _Jv_CallNonvirtualMethodA.  Changed interface; overloaded.
	Include <jni.h>.
	(COPY): Removed.
	(invoke): Use _Jv_CallAnyMethodA.
	(VAL): Redefined.
	* java/lang/Class.h (Class): Declare JvGetFirstStaticField,
	JvNumStaticFields, JvNumMethods, and JvGetFirstMethod as friend
	functions.
	(struct _Jv_Method): Added getNextMethod method.
	(JvNumMethods): New function.
	(JvGetFirstMethod): Likewise.
	* gcj/field.h (JvGetFirstStaticField): New function.
	(JvNumStaticFields): Likewise.
	(getNextField): Renamed from getNextInstanceField.
	(struct _Jv_Field): New method getClass.
	* jni.cc: Wrote many new functions.
	* include/jni.h (JNI_TRUE): Define.
	(JNI_FALSE): Likewise.
	(jobject, jclass, jstring, jarray, jthrowable, jobjectArray,
	jbyteArray, jshortArray, jintArray, jlongArray, jbooleanArray,
	jcharArray, jfloatArray, jdoubleArray): New typedefs.
	(jfieldID, jmethodID): Likewise.
	(JNI_COMMIT, JNI_ABORT): New defines.
	(JNINativeMethod): New struct.
	(struct JNINativeInterface): Correctly declared more entries.
	(class _Jv_JNIEnv): Added `ex' member.
	(JNI_VERSION_1_1): New define.
	(JNI_VERSION_1_2): Likewise.

	* boehm.cc (_Jv_MarkObj): Use getNextField, not
	getNextInstanceField.

Tom

Index: boehm.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/boehm.cc,v
retrieving revision 1.12
diff -u -r1.12 boehm.cc
--- boehm.cc	2000/01/19 18:39:23	1.12
+++ boehm.cc	2000/01/21 23:41:38
@@ -1,6 +1,6 @@
 // boehm.cc - interface between libjava and Boehm GC.
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -256,7 +256,7 @@
 		  MAYBE_MARK (w, mark_stack_ptr, mark_stack_limit,
 			      obj, elabel);
 		}
-	      field = field->getNextInstanceField ();
+	      field = field->getNextField ();
 	    }
 	  klass = klass->getSuperclass();
 	}
Index: jni.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/jni.cc,v
retrieving revision 1.3
diff -u -r1.3 jni.cc
--- jni.cc	2000/01/19 18:39:23	1.3
+++ jni.cc	2000/01/21 23:41:44
@@ -1,6 +1,6 @@
 // jni.cc - JNI implementation, including the jump table.
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -8,13 +8,79 @@
 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 details.  */
 
+// Note: currently we take the approach of not checking most
+// arguments.  Instead we could do more checking conditionally (e.g.,
+// if DEBUG is defined).  That might be beneficial in some cases,
+// though to me it seems that one could just as easily use the
+// debugger.
+
 #include <config.h>
 
 #include <stddef.h>
 
+// Must define this before jni.h.
+#define GCJ_JV_JNIENV_FRIEND \
+    friend jthrowable &get_throwable (JNIEnv *)
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java-assert.h>
 #include <jni.h>
 #include <gcj/field.h>
+#include <java/lang/Throwable.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/InstantiationException.h>
+#include <java/lang/NoSuchFieldError.h>
+#include <java/lang/NoSuchMethodError.h>
+#include <java/lang/reflect/Constructor.h>
+#include <java/lang/reflect/Modifier.h>
+
+#define ClassClass _CL_Q34java4lang5Class
+extern java::lang::Class ClassClass;
+#define ObjectClass _CL_Q34java4lang6Object
+extern java::lang::Class ObjectClass;
+
+// This enum is used to select different template instantiations in
+// the invocation code.
+enum invocation_type
+{
+  normal,
+  nonvirtual,
+  static_type,
+  constructor
+};
+
+
+
+// Tell the GC that a certain pointer is live.
+static void
+mark_for_gc (void *)
+{
+  // FIXME.
+}
+
+// Unmark a pointer.
+static void
+unmark_for_gc (void *)
+{
+  // FIXME.
+}
+
+// Return throwable in env.
+jthrowable &
+get_throwable (JNIEnv *env)
+{
+  return env->ex;
+}
+
+
 
+static jint
+_Jv_JNI_GetVersion (JNIEnv *)
+{
+  return JNI_VERSION_1_2;
+}
+
 static jclass
 _Jv_JNI_GetSuperclass (JNIEnv *, jclass clazz)
 {
@@ -27,34 +93,556 @@
   return clazz1->isAssignableFrom (clazz2);
 }
 
+static jint
+_Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
+{
+  get_throwable (env) = obj;
+  return 0;
+}
+
+static jint
+_Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
+{
+  using namespace java::lang::reflect;
+
+  JArray<jclass> *argtypes
+    = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
+
+  jclass *elts = elements (argtypes);
+  elts[0] = &StringClass;
+
+  // FIXME: exception processing.
+  Constructor *cons = clazz->getConstructor (argtypes);
+
+  jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
+  jobject *velts = elements (values);
+  velts[0] = JvNewStringUTF (message);
+
+  // FIXME: exception processing.
+  jobject obj = cons->newInstance (values);
+
+  get_throwable (env) = reinterpret_cast<jthrowable> (obj);
+  return 0;
+}
+
+static jthrowable
+_Jv_JNI_ExceptionOccurred (JNIEnv *env)
+{
+  return get_throwable (env);
+}
+
+static void
+_Jv_JNI_ExceptionDescribe (JNIEnv *env)
+{
+  if (get_throwable (env) != NULL)
+    get_throwable (env)->printStackTrace();
+}
+
+static void
+_Jv_JNI_ExceptionClear (JNIEnv *env)
+{
+  get_throwable (env) = NULL;
+}
+
+static void
+_Jv_JNI_FatalError (JNIEnv *, const char *message)
+{
+  JvFail (message);
+}
+
+static jboolean
+_Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
+{
+  return obj1 == obj2;
+}
+
 static jobject
-_Jv_JNI_GetObjectField (JNIEnv *, jobject obj, jfieldID field) 
+_Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
 {
-  return _Jv_GetObjectField (obj, field);
+  jobject obj = NULL;
+  using namespace java::lang::reflect;
+  if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
+    get_throwable (env) = new java::lang::InstantiationException ();
+  else
+    {
+      // FIXME: exception processing.
+      // FIXME: will this work for String?
+      obj = JvAllocObject (clazz);
+    }
+
+  return obj;
 }
 
-static jbyte
-_Jv_JNI_GetByteField (JNIEnv *, jobject obj, jfieldID field) 
+static jclass
+_Jv_JNI_GetObjectClass (JNIEnv *, jobject obj)
 {
-  return _Jv_GetByteField (obj, field);
+  return obj->getClass();
 }
 
-static jshort
-_Jv_JNI_GetShortField (JNIEnv *, jobject obj, jfieldID field) 
+static jboolean
+_Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
 {
-  return _Jv_GetShortField (obj, field);
+  return clazz->isInstance(obj);
 }
 
-static jint
-_Jv_JNI_GetIntField (JNIEnv *, jobject obj, jfieldID field) 
+
+
+//
+// This section concerns method invocation.
+//
+
+template<jboolean is_static>
+static jmethodID
+_Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
+			const char *name, const char *sig)
+{
+  // FIXME: exception processing.
+  _Jv_InitClass (clazz);
+
+  _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
+  _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
+
+  JvAssert (! clazz->isPrimitive());
+
+  using namespace java::lang::reflect;
+
+  while (clazz != NULL)
+    {
+      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();
+	}
+
+      clazz = clazz->getSuperclass ();
+    }
+
+  get_throwable (env) = new java::lang::NoSuchMethodError ();
+  return NULL;
+}
+
+// This is a helper function which turns a va_list into an array of
+// `jvalue's.  It needs signature information in order to do its work.
+// The array of values must already be allocated.
+static void
+array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
+{
+  jclass *arg_elts = elements (arg_types);
+  for (int i = 0; i < arg_types->length; ++i)
+    {
+      if (arg_elts[i] == JvPrimClass (byte))
+	values[i].b = va_arg (vargs, jbyte);
+      else if (arg_elts[i] == JvPrimClass (short))
+	values[i].s = va_arg (vargs, jshort);
+      else if (arg_elts[i] == JvPrimClass (int))
+	values[i].i = va_arg (vargs, jint);
+      else if (arg_elts[i] == JvPrimClass (long))
+	values[i].j = va_arg (vargs, jlong);
+      else if (arg_elts[i] == JvPrimClass (float))
+	values[i].f = va_arg (vargs, jfloat);
+      else if (arg_elts[i] == JvPrimClass (double))
+	values[i].d = va_arg (vargs, jdouble);
+      else if (arg_elts[i] == JvPrimClass (boolean))
+	values[i].z = va_arg (vargs, jboolean);
+      else if (arg_elts[i] == JvPrimClass (char))
+	values[i].c = va_arg (vargs, jchar);
+      else
+	{
+	  // An object.
+	  values[i].l = va_arg (vargs, jobject);
+	}
+    }
+}
+
+// This can call any sort of method: virtual, "nonvirtual", static, or
+// constructor.
+template<typename T, invocation_type style>
+static T
+_Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
+			jmethodID id, va_list vargs)
+{
+  if (style == normal)
+    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
+
+  jclass decl_class = klass ? klass : obj->getClass ();
+  JvAssert (decl_class != NULL);
+
+  jclass return_type;
+  JArray<jclass> *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);
+
+  jvalue result;
+  jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+				      style == constructor,
+				      arg_types, args, &result);
+
+  if (ex != NULL)
+    get_throwable (env) = ex;
+
+  // We cheat a little here.  FIXME.
+  return * (T *) &result;
+}
+
+template<typename T, invocation_type style>
+static T
+_Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
+		       jmethodID method, ...)
+{
+  va_list args;
+  T result;
+
+  va_start (args, method);
+  result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
+  va_end (args);
+
+  return result;
+}
+
+template<typename T, invocation_type style>
+static T
+_Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
+			jmethodID id, jvalue *args)
+{
+  if (style == normal)
+    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
+
+  jclass decl_class = klass ? klass : obj->getClass ();
+  JvAssert (decl_class != NULL);
+
+  jclass return_type;
+  JArray<jclass> *arg_types;
+  // FIXME: exception processing.
+  _Jv_GetTypesFromSignature (id, decl_class,
+			     &arg_types, &return_type);
+
+  jvalue result;
+  jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+				      style == constructor,
+				      arg_types, args, &result);
+
+  if (ex != NULL)
+    get_throwable (env) = ex;
+
+  // We cheat a little here.  FIXME.
+  return * (T *) &result;
+}
+
+template<invocation_type style>
+static void
+_Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
+			    jmethodID id, va_list vargs)
+{
+  if (style == normal)
+    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
+
+  jclass decl_class = klass ? klass : obj->getClass ();
+  JvAssert (decl_class != NULL);
+
+  jclass return_type;
+  JArray<jclass> *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);
+
+  jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+				      style == constructor,
+				      arg_types, args, NULL);
+
+  if (ex != NULL)
+    get_throwable (env) = ex;
+}
+
+template<invocation_type style>
+static void
+_Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
+			   jmethodID method, ...)
+{
+  va_list args;
+
+  va_start (args, method);
+  _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
+  va_end (args);
+}
+
+template<invocation_type style>
+static void
+_Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
+			    jmethodID id, jvalue *args)
+{
+  if (style == normal)
+    id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
+
+  jclass decl_class = klass ? klass : obj->getClass ();
+  JvAssert (decl_class != NULL);
+
+  jclass return_type;
+  JArray<jclass> *arg_types;
+  // FIXME: exception processing.
+  _Jv_GetTypesFromSignature (id, decl_class,
+			     &arg_types, &return_type);
+
+  jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+				      style == constructor,
+				      arg_types, args, NULL);
+
+  if (ex != NULL)
+    get_throwable (env) = ex;
+}
+
+// Functions with this signature are used to implement functions in
+// the CallMethod family.
+template<typename T>
+static T
+_Jv_JNI_CallMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
+{
+  return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
+}
+
+// Functions with this signature are used to implement functions in
+// the CallMethod family.
+template<typename T>
+static T
+_Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
+{
+  va_list args;
+  T result;
+
+  va_start (args, id);
+  result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
+  va_end (args);
+
+  return result;
+}
+
+// Functions with this signature are used to implement functions in
+// the CallMethod family.
+template<typename T>
+static T
+_Jv_JNI_CallMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
+{
+  return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
+}
+
+static void
+_Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID id, va_list args)
+{
+  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
+}
+
+static void
+_Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
+{
+  va_list args;
+
+  va_start (args, id);
+  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
+  va_end (args);
+}
+
+static void
+_Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID id, jvalue *args)
+{
+  _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
+}
+
+// Functions with this signature are used to implement functions in
+// the CallStaticMethod family.
+template<typename T>
+static T
+_Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
+			   jmethodID id, va_list args)
+{
+  return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
+}
+
+// Functions with this signature are used to implement functions in
+// the CallStaticMethod family.
+template<typename T>
+static T
+_Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
+{
+  va_list args;
+  T result;
+
+  va_start (args, id);
+  result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
+						   id, args);
+  va_end (args);
+
+  return result;
+}
+
+// Functions with this signature are used to implement functions in
+// the CallStaticMethod family.
+template<typename T>
+static T
+_Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
+			   jvalue *args)
+{
+  return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
+}
+
+static void
+_Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass, jmethodID id,
+			       va_list args)
+{
+  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
+}
+
+static void
+_Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass, jmethodID id, ...)
+{
+  va_list args;
+
+  va_start (args, id);
+  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
+  va_end (args);
+}
+
+static void
+_Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass, jmethodID id,
+			       jvalue *args)
+{
+  _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
+}
+
+static jobject
+_Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
+		    jmethodID id, va_list args)
+{
+  return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
+						       id, args);
+}
+
+static jobject
+_Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
+{
+  va_list args;
+  jobject result;
+
+  va_start (args, id);
+  result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
+							 id, args);
+  va_end (args);
+
+  return result;
+}
+
+static jobject
+_Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
+		    jvalue *args)
+{
+  return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
+						       id, args);
+}
+
+
+
+template<typename T>
+static T
+_Jv_JNI_GetField (JNIEnv *, jobject obj, jfieldID field) 
+{
+  T *ptr = (T *) ((char *) obj + field->getOffset ());
+  return *ptr;
+}
+
+template<typename T>
+static void
+_Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
+{
+  T *ptr = (T *) ((char *) obj + field->getOffset ());
+  *ptr = value;
+}
+
+template<jboolean is_static>
+static jfieldID
+_Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
+		       const char *name, const char *sig)
+{
+  // FIXME: exception processing.
+  _Jv_InitClass (clazz);
+
+  _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: 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)
+	{
+	  // The field is resolved as a side effect of class
+	  // initialization.
+	  JvAssert (field->isResolved ());
+
+	  _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
+
+	  if (_Jv_equalUtf8Consts (f_name, a_name)
+	      && field->getClass() == field_class)
+	    return field;
+
+	  field = field->getNextField ();
+	}
+
+      clazz = clazz->getSuperclass ();
+    }
+
+  get_throwable (env) = new java::lang::NoSuchFieldError ();
+  return NULL;
+}
+
+template<typename T>
+static T
+_Jv_JNI_GetStaticField (JNIEnv *, jclass, jfieldID field)
+{
+  T *ptr = (T *) field->u.addr;
+  return *ptr;
+}
+
+template<typename T>
+static void
+_Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
 {
-  return _Jv_GetIntField (obj, field);
+  T *ptr = (T *) field->u.addr;
+  *ptr = value;
 }
 
-static jlong
-_Jv_JNI_GetLongField (JNIEnv *, jobject obj, jfieldID field) 
+static jstring
+_Jv_JNI_NewString (JNIEnv *, const jchar *unichars, jsize len)
 {
-  return _Jv_GetLongField (obj, field);
+  // FIXME: exception processing.
+  jstring r = _Jv_NewString (unichars, len);
+  return r;
 }
 
 static jsize
@@ -63,6 +651,173 @@
   return string->length();
 }
 
+static const jchar *
+_Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
+{
+  jchar *result = _Jv_GetStringChars (string);
+  mark_for_gc (result);
+  if (isCopy)
+    *isCopy = false;
+  return (const jchar *) result;
+}
+
+static void
+_Jv_JNI_ReleaseStringChars (JNIEnv *, jstring, const jchar *chars)
+{
+  unmark_for_gc ((void *) chars);
+}
+
+static jstring
+_Jv_JNI_NewStringUTF (JNIEnv *, const char *bytes)
+{
+  // FIXME: exception processing.
+  jstring r = JvNewStringUTF (bytes);
+  return r;
+}
+
+static jsize
+_Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
+{
+  return JvGetStringUTFLength (string);
+}
+
+static const char *
+_Jv_JNI_GetStringUTFChars (JNIEnv *, 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';
+
+  if (isCopy)
+    *isCopy = true;
+
+  return (const char *) r;
+}
+
+static void
+_Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
+{
+  _Jv_Free ((void *) utf);
+}
+
+static jsize
+_Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
+{
+  return array->length;
+}
+
+static jarray
+_Jv_JNI_NewObjectArray (JNIEnv *, jsize length, jclass elementClass,
+			jobject init)
+{
+  // FIXME: exception processing.
+  jarray result = JvNewObjectArray (length, elementClass, init);
+  return result;
+}
+
+static jobject
+_Jv_JNI_GetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index)
+{
+  jobject *elts = elements (array);
+  return elts[index];
+}
+
+static void
+_Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
+			       jobject value)
+{
+  // FIXME: exception processing.
+  _Jv_CheckArrayStore (array, value);
+  jobject *elts = elements (array);
+  elts[index] = value;
+}
+
+template<typename T, jclass K>
+static JArray<T> *
+_Jv_JNI_NewPrimitiveArray (JNIEnv *, jsize length)
+{
+  return (JArray<T> *) _Jv_NewPrimArray (K, length);
+}
+
+template<typename T>
+static T *
+_Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
+				   jboolean *isCopy)
+{
+  T *elts = elements (array);
+  if (isCopy)
+    {
+      // We elect never to copy.
+      *isCopy = false;
+    }
+  mark_for_gc (elts);
+  return elts;
+}
+
+template<typename T>
+static void
+_Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *,
+				       T *elems, jint /* mode */)
+{
+  // Note that we ignore MODE.  We can do this because we never copy
+  // the array elements.  My reading of the JNI documentation is that
+  // this is an option for the implementor.
+  unmark_for_gc (elems);
+}
+
+template<typename T>
+static void
+_Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
+				 jsize start, jsize len,
+				 T *buf)
+{
+  if (start < 0 || len >= array->length || start + len >= array->length)
+    {
+      // FIXME: index.
+      get_throwable (env) = new java::lang::ArrayIndexOutOfBoundsException ();
+    }
+  else
+    {
+      T *elts = elements (array) + start;
+      memcpy (buf, elts, len * sizeof (T));
+    }
+}
+
+template<typename T>
+static void
+_Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array, 
+				 jsize start, jsize len, T *buf)
+{
+  if (start < 0 || len >= array->length || start + len >= array->length)
+    {
+      // FIXME: index.
+      get_throwable (env) = new java::lang::ArrayIndexOutOfBoundsException ();
+    }
+  else
+    {
+      T *elts = elements (array) + start;
+      memcpy (elts, buf, len * sizeof (T));
+    }
+}
+
+static jint
+_Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
+{
+  // FIXME: exception processing.
+  jint r = _Jv_MonitorEnter (obj);
+  return r;
+}
+
+static jint
+_Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
+{
+  // FIXME: exception processing.
+  jint r = _Jv_MonitorExit (obj);
+  return r;
+}
+
 // JDK 1.2
 jobject
 _Jv_JNI_ToReflectedField (JNIEnv *, jclass cls, jfieldID fieldID)
@@ -82,227 +837,234 @@
 }
 
 #define NOT_IMPL NULL
+#define RESERVED NULL
 
 struct JNINativeInterface _Jv_JNIFunctions =
 {
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NOT_IMPL /* GetVersion */,
+  RESERVED,
+  RESERVED,
+  RESERVED,
+  RESERVED,
+  _Jv_JNI_GetVersion,
   NOT_IMPL /* DefineClass */,
   NOT_IMPL /* FindClass */,
-  NULL,
-  NULL,
-  NULL,
+  RESERVED,
+  RESERVED,
+  RESERVED,
   _Jv_JNI_GetSuperclass,
   IsAssignableFrom,
-  NULL,
-  NOT_IMPL /* Throw */,
-  NOT_IMPL /* ThrowNew */,
-  NOT_IMPL /* ExceptionOccurred */,
-  NOT_IMPL /* ExceptionDescribe */,
-  NOT_IMPL /* ExceptionClear */,
-  NOT_IMPL /* FatalError */,
-  NOT_IMPL /* NULL */,
-  NOT_IMPL /* NULL */,
+  RESERVED,
+  _Jv_JNI_Throw,
+  _Jv_JNI_ThrowNew,
+  _Jv_JNI_ExceptionOccurred,
+  _Jv_JNI_ExceptionDescribe,
+  _Jv_JNI_ExceptionClear,
+  _Jv_JNI_FatalError,
+  RESERVED,
+  RESERVED,
   NOT_IMPL /* NewGlobalRef */,
   NOT_IMPL /* DeleteGlobalRef */,
   NOT_IMPL /* DeleteLocalRef */,
-  NOT_IMPL /* IsSameObject */,
-  NOT_IMPL /* NULL */,
-  NOT_IMPL /* NULL */,
-  NOT_IMPL /* AllocObject */,
-  NOT_IMPL /* NewObject */,
-  NOT_IMPL /* NewObjectV */,
-  NOT_IMPL /* NewObjectA */,
-  NOT_IMPL /* GetObjectClass */,
-  NOT_IMPL /* IsInstanceOf */,
-  NOT_IMPL /* GetMethodID */,
-  NOT_IMPL /* CallObjectMethod */,
-  NOT_IMPL /* CallObjectMethodV */,
-  NOT_IMPL /* CallObjectMethodA */,
-  NOT_IMPL /* CallBooleanMethod */,
-  NOT_IMPL /* CallBooleanMethodV */,
-  NOT_IMPL /* CallBooleanMethodA */,
-  NOT_IMPL /* CallByteMethod */,
-  NOT_IMPL /* CallByteMethodV */,
-  NOT_IMPL /* CallByteMethodA */,
-  NOT_IMPL /* CallCharMethod */,
-  NOT_IMPL /* CallCharMethodV */,
-  NOT_IMPL /* CallCharMethodA */,
-  NOT_IMPL /* CallShortMethod */,
-  NOT_IMPL /* CallShortMethodV */,
-  NOT_IMPL /* CallShortMethodA */,
-  NOT_IMPL /* CallIntMethod */,
-  NOT_IMPL /* CallIntMethodV */,
-  NOT_IMPL /* CallIntMethodA */,
-  NOT_IMPL /* CallLongMethod */,
-  NOT_IMPL /* CallLongMethodV */,
-  NOT_IMPL /* CallLongMethodA */,
-  NOT_IMPL /* CallFloatMethod */,
-  NOT_IMPL /* CallFloatMethodV */,
-  NOT_IMPL /* CallFloatMethodA */,
-  NOT_IMPL /* CallDoubleMethod */,
-  NOT_IMPL /* CallDoubleMethodV */,
-  NOT_IMPL /* CallDoubleMethodA */,
-  NOT_IMPL /* CallVoidMethod */,
-  NOT_IMPL /* CallVoidMethodV */,
-  NOT_IMPL /* CallVoidMethodA */,
-  NOT_IMPL /* CallNonvirtualObjectMethod */,
-  NOT_IMPL /* CallNonvirtualObjectMethodV */,
-  NOT_IMPL /* CallNonvirtualObjectMethodA */,
-  NOT_IMPL /* CallNonvirtualBooleanMethod */,
-  NOT_IMPL /* CallNonvirtualBooleanMethodV */,
-  NOT_IMPL /* CallNonvirtualBooleanMethodA */,
-  NOT_IMPL /* CallNonvirtualByteMethod */,
-  NOT_IMPL /* CallNonvirtualByteMethodV */,
-  NOT_IMPL /* CallNonvirtualByteMethodA */,
-  NOT_IMPL /* CallNonvirtualCharMethod */,
-  NOT_IMPL /* CallNonvirtualCharMethodV */,
-  NOT_IMPL /* CallNonvirtualCharMethodA */,
-  NOT_IMPL /* CallNonvirtualShortMethod */,
-  NOT_IMPL /* CallNonvirtualShortMethodV */,
-  NOT_IMPL /* CallNonvirtualShortMethodA */,
-  NOT_IMPL /* CallNonvirtualIntMethod */,
-  NOT_IMPL /* CallNonvirtualIntMethodV */,
-  NOT_IMPL /* CallNonvirtualIntMethodA */,
-  NOT_IMPL /* CallNonvirtualLongMethod */,
-  NOT_IMPL /* CallNonvirtualLongMethodV */,
-  NOT_IMPL /* CallNonvirtualLongMethodA */,
-  NOT_IMPL /* CallNonvirtualFloatMethod */,
-  NOT_IMPL /* CallNonvirtualFloatMethodV */,
-  NOT_IMPL /* CallNonvirtualFloatMethodA */,
-  NOT_IMPL /* CallNonvirtualDoubleMethod */,
-  NOT_IMPL /* CallNonvirtualDoubleMethodV */,
-  NOT_IMPL /* CallNonvirtualDoubleMethodA */,
-  NOT_IMPL /* CallNonvirtualVoidMethod */,
-  NOT_IMPL /* CallNonvirtualVoidMethodV */,
-  NOT_IMPL /* CallNonvirtualVoidMethodA */,
-  NOT_IMPL /* GetFieldID */,
-  _Jv_JNI_GetObjectField,
-  NOT_IMPL /* GetBooleanField */,
-  _Jv_JNI_GetByteField,
-  NOT_IMPL /* GetCharField */,
-  _Jv_JNI_GetShortField,
-  _Jv_JNI_GetIntField,
-  _Jv_JNI_GetLongField,
-  NOT_IMPL /* GetFloatField */,
-  NOT_IMPL /* GetDoubleField */,
-  NOT_IMPL /* SetObjectField */,
-  NOT_IMPL /* SetBooleanField */,
-  NOT_IMPL /* SetByteField */,
-  NOT_IMPL /* SetCharField */,
-  NOT_IMPL /* SetShortField */,
-  NOT_IMPL /* SetIntField */,
-  NOT_IMPL /* SetLongField */,
-  NOT_IMPL /* SetFloatField */,
-  NOT_IMPL /* SetDoubleField */,
-  NOT_IMPL /* GetStaticMethodID */,
-  NOT_IMPL /* CallStaticObjectMethod */,
-  NOT_IMPL /* CallStaticObjectMethodV */,
-  NOT_IMPL /* CallStaticObjectMethodA */,
-  NOT_IMPL /* CallStaticBooleanMethod */,
-  NOT_IMPL /* CallStaticBooleanMethodV */,
-  NOT_IMPL /* CallStaticBooleanMethodA */,
-  NOT_IMPL /* CallStaticByteMethod */,
-  NOT_IMPL /* CallStaticByteMethodV */,
-  NOT_IMPL /* CallStaticByteMethodA */,
-  NOT_IMPL /* CallStaticCharMethod */,
-  NOT_IMPL /* CallStaticCharMethodV */,
-  NOT_IMPL /* CallStaticCharMethodA */,
-  NOT_IMPL /* CallStaticShortMethod */,
-  NOT_IMPL /* CallStaticShortMethodV */,
-  NOT_IMPL /* CallStaticShortMethodA */,
-  NOT_IMPL /* CallStaticIntMethod */,
-  NOT_IMPL /* CallStaticIntMethodV */,
-  NOT_IMPL /* CallStaticIntMethodA */,
-  NOT_IMPL /* CallStaticLongMethod */,
-  NOT_IMPL /* CallStaticLongMethodV */,
-  NOT_IMPL /* CallStaticLongMethodA */,
-  NOT_IMPL /* CallStaticFloatMethod */,
-  NOT_IMPL /* CallStaticFloatMethodV */,
-  NOT_IMPL /* CallStaticFloatMethodA */,
-  NOT_IMPL /* CallStaticDoubleMethod */,
-  NOT_IMPL /* CallStaticDoubleMethodV */,
-  NOT_IMPL /* CallStaticDoubleMethodA */,
-  NOT_IMPL /* CallStaticVoidMethod */,
-  NOT_IMPL /* CallStaticVoidMethodV */,
-  NOT_IMPL /* CallStaticVoidMethodA */,
-  NOT_IMPL /* GetStaticFieldID */,
-  NOT_IMPL /* GetStaticObjectField */,
-  NOT_IMPL /* GetStaticBooleanField */,
-  NOT_IMPL /* GetStaticByteField */,
-  NOT_IMPL /* GetStaticCharField */,
-  NOT_IMPL /* GetStaticShortField */,
-  NOT_IMPL /* GetStaticIntField */,
-  NOT_IMPL /* GetStaticLongField */,
-  NOT_IMPL /* GetStaticFloatField */,
-  NOT_IMPL /* GetStaticDoubleField */,
-  NOT_IMPL /* SetStaticObjectField */,
-  NOT_IMPL /* SetStaticBooleanField */,
-  NOT_IMPL /* SetStaticByteField */,
-  NOT_IMPL /* SetStaticCharField */,
-  NOT_IMPL /* SetStaticShortField */,
-  NOT_IMPL /* SetStaticIntField */,
-  NOT_IMPL /* SetStaticLongField */,
-  NOT_IMPL /* SetStaticFloatField */,
-  NOT_IMPL /* SetStaticDoubleField */,
-  NOT_IMPL /* NewString */,
+  _Jv_JNI_IsSameObject,
+  RESERVED,
+  RESERVED,
+  _Jv_JNI_AllocObject,
+  _Jv_JNI_NewObject,
+  _Jv_JNI_NewObjectV,
+  _Jv_JNI_NewObjectA,
+  _Jv_JNI_GetObjectClass,
+  _Jv_JNI_IsInstanceOf,
+  _Jv_JNI_GetAnyMethodID<false>,
+
+  _Jv_JNI_CallMethod<jobject>,
+  _Jv_JNI_CallMethodV<jobject>,
+  _Jv_JNI_CallMethodA<jobject>,
+  _Jv_JNI_CallMethod<jboolean>,
+  _Jv_JNI_CallMethodV<jboolean>,
+  _Jv_JNI_CallMethodA<jboolean>,
+  _Jv_JNI_CallMethod<jbyte>,
+  _Jv_JNI_CallMethodV<jbyte>,
+  _Jv_JNI_CallMethodA<jbyte>,
+  _Jv_JNI_CallMethod<jchar>,
+  _Jv_JNI_CallMethodV<jchar>,
+  _Jv_JNI_CallMethodA<jchar>,
+  _Jv_JNI_CallMethod<jshort>,
+  _Jv_JNI_CallMethodV<jshort>,
+  _Jv_JNI_CallMethodA<jshort>,
+  _Jv_JNI_CallMethod<jint>,
+  _Jv_JNI_CallMethodV<jint>,
+  _Jv_JNI_CallMethodA<jint>,
+  _Jv_JNI_CallMethod<jlong>,
+  _Jv_JNI_CallMethodV<jlong>,
+  _Jv_JNI_CallMethodA<jlong>,
+  _Jv_JNI_CallMethod<jfloat>,
+  _Jv_JNI_CallMethodV<jfloat>,
+  _Jv_JNI_CallMethodA<jfloat>,
+  _Jv_JNI_CallMethod<jdouble>,
+  _Jv_JNI_CallMethodV<jdouble>,
+  _Jv_JNI_CallMethodA<jdouble>,
+  _Jv_JNI_CallVoidMethod,
+  _Jv_JNI_CallVoidMethodV,
+  _Jv_JNI_CallVoidMethodA,
+
+  // Nonvirtual method invocation functions follow.
+  _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jint, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,
+  _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,
+  _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,
+  _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,
+  _Jv_JNI_CallAnyVoidMethod<nonvirtual>,
+  _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,
+  _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,
+
+  _Jv_JNI_GetAnyFieldID<false>,
+  _Jv_JNI_GetField<jobject>,
+  _Jv_JNI_GetField<jboolean>,
+  _Jv_JNI_GetField<jbyte>,
+  _Jv_JNI_GetField<jchar>,
+  _Jv_JNI_GetField<jshort>,
+  _Jv_JNI_GetField<jint>,
+  _Jv_JNI_GetField<jlong>,
+  _Jv_JNI_GetField<jfloat>,
+  _Jv_JNI_GetField<jdouble>,
+  _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<true>,
+
+  _Jv_JNI_CallStaticMethod<jobject>,
+  _Jv_JNI_CallStaticMethodV<jobject>,
+  _Jv_JNI_CallStaticMethodA<jobject>,
+  _Jv_JNI_CallStaticMethod<jboolean>,
+  _Jv_JNI_CallStaticMethodV<jboolean>,
+  _Jv_JNI_CallStaticMethodA<jboolean>,
+  _Jv_JNI_CallStaticMethod<jbyte>,
+  _Jv_JNI_CallStaticMethodV<jbyte>,
+  _Jv_JNI_CallStaticMethodA<jbyte>,
+  _Jv_JNI_CallStaticMethod<jchar>,
+  _Jv_JNI_CallStaticMethodV<jchar>,
+  _Jv_JNI_CallStaticMethodA<jchar>,
+  _Jv_JNI_CallStaticMethod<jshort>,
+  _Jv_JNI_CallStaticMethodV<jshort>,
+  _Jv_JNI_CallStaticMethodA<jshort>,
+  _Jv_JNI_CallStaticMethod<jint>,
+  _Jv_JNI_CallStaticMethodV<jint>,
+  _Jv_JNI_CallStaticMethodA<jint>,
+  _Jv_JNI_CallStaticMethod<jlong>,
+  _Jv_JNI_CallStaticMethodV<jlong>,
+  _Jv_JNI_CallStaticMethodA<jlong>,
+  _Jv_JNI_CallStaticMethod<jfloat>,
+  _Jv_JNI_CallStaticMethodV<jfloat>,
+  _Jv_JNI_CallStaticMethodA<jfloat>,
+  _Jv_JNI_CallStaticMethod<jdouble>,
+  _Jv_JNI_CallStaticMethodV<jdouble>,
+  _Jv_JNI_CallStaticMethodA<jdouble>,
+  _Jv_JNI_CallStaticVoidMethod,
+  _Jv_JNI_CallStaticVoidMethodV,
+  _Jv_JNI_CallStaticVoidMethodA,
+
+  _Jv_JNI_GetAnyFieldID<true>,
+  _Jv_JNI_GetStaticField<jobject>,
+  _Jv_JNI_GetStaticField<jboolean>,
+  _Jv_JNI_GetStaticField<jbyte>,
+  _Jv_JNI_GetStaticField<jchar>,
+  _Jv_JNI_GetStaticField<jshort>,
+  _Jv_JNI_GetStaticField<jint>,
+  _Jv_JNI_GetStaticField<jlong>,
+  _Jv_JNI_GetStaticField<jfloat>,
+  _Jv_JNI_GetStaticField<jdouble>,
+  _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,
-  NOT_IMPL /* GetStringChars */,
-  NOT_IMPL /* ReleaseStringChars */,
-  NOT_IMPL /* NewStringUTF */,
-  NOT_IMPL /* GetStringUTFLength */,
-  NOT_IMPL /* GetStringUTFChars */,
-  NOT_IMPL /* ReleaseStringUTFChars */,
-  NOT_IMPL /* GetArrayLength */,
-  NOT_IMPL /* NewObjectArray */,
-  NOT_IMPL /* GetObjectArrayElement */,
-  NOT_IMPL /* SetObjectArrayElement */,
-  NOT_IMPL /* NewBooleanArray */,
-  NOT_IMPL /* NewByteArray */,
-  NOT_IMPL /* NewCharArray */,
-  NOT_IMPL /* NewShortArray */,
-  NOT_IMPL /* NewIntArray */,
-  NOT_IMPL /* NewLongArray */,
-  NOT_IMPL /* NewFloatArray */,
-  NOT_IMPL /* NewDoubleArray */,
-  NOT_IMPL /* GetBooleanArrayElements */,
-  NOT_IMPL /* GetByteArrayElements */,
-  NOT_IMPL /* GetCharArrayElements */,
-  NOT_IMPL /* GetShortArrayElements */,
-  NOT_IMPL /* GetIntArrayElements */,
-  NOT_IMPL /* GetLongArrayElements */,
-  NOT_IMPL /* GetFloatArrayElements */,
-  NOT_IMPL /* GetDoubleArrayElements */,
-  NOT_IMPL /* ReleaseBooleanArrayElements */,
-  NOT_IMPL /* ReleaseByteArrayElements */,
-  NOT_IMPL /* ReleaseCharArrayElements */,
-  NOT_IMPL /* ReleaseShortArrayElements */,
-  NOT_IMPL /* ReleaseIntArrayElements */,
-  NOT_IMPL /* ReleaseLongArrayElements */,
-  NOT_IMPL /* ReleaseFloatArrayElements */,
-  NOT_IMPL /* ReleaseDoubleArrayElements */,
-  NOT_IMPL /* GetBooleanArrayRegion */,
-  NOT_IMPL /* GetByteArrayRegion */,
-  NOT_IMPL /* GetCharArrayRegion */,
-  NOT_IMPL /* GetShortArrayRegion */,
-  NOT_IMPL /* GetIntArrayRegion */,
-  NOT_IMPL /* GetLongArrayRegion */,
-  NOT_IMPL /* GetFloatArrayRegion */,
-  NOT_IMPL /* GetDoubleArrayRegion */,
-  NOT_IMPL /* SetBooleanArrayRegion */,
-  NOT_IMPL /* SetByteArrayRegion */,
-  NOT_IMPL /* SetCharArrayRegion */,
-  NOT_IMPL /* SetShortArrayRegion */,
-  NOT_IMPL /* SetIntArrayRegion */,
-  NOT_IMPL /* SetLongArrayRegion */,
-  NOT_IMPL /* SetFloatArrayRegion */,
-  NOT_IMPL /* SetDoubleArrayRegion */,
+  _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_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
+  _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,
+  _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,
+  _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,
+  _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,
+  _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,
+  _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,
+  _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>,
+  _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 */,
-  NOT_IMPL /* MonitorEnter */,
-  NOT_IMPL /* MonitorExit */,
+  _Jv_JNI_MonitorEnter,
+  _Jv_JNI_MonitorExit,
   NOT_IMPL /* GetJavaVM */,
 };
Index: gcj/field.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/gcj/field.h,v
retrieving revision 1.2
diff -u -r1.2 field.h
--- field.h	2000/01/19 18:39:23	1.2
+++ field.h	2000/01/21 23:41:44
@@ -1,6 +1,6 @@
 // field.h - Header file for fieldID instances.  -*- c++ -*-
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -30,7 +30,7 @@
   _Jv_ushort		flags;
 
 #ifdef COMPACT_FIELDS
-  short			nameIndex;  /* ofsfet in class's name table */
+  short			nameIndex;  /* offset in class's name table */
 #else
   _Jv_ushort		bsize;  /* not really needed ... */
 #endif
@@ -51,7 +51,7 @@
   jobject getObjectField (jobject obj)
   { return *(jobject *)((char *)obj + getOffset ()); }
 
-  jfieldID getNextInstanceField () { return this + 1; }
+  jfieldID getNextField () { return this + 1; }
 
   jboolean isRef () 
     { 
@@ -66,6 +66,12 @@
 	}
     }
 
+  jclass getClass ()
+  {
+    JvAssert (isResolved ());
+    return type;
+  }
+
   // FIXME - may need to mask off internal flags.
   int getModifiers() { return flags; }
 
@@ -79,6 +85,7 @@
 };
 
 #ifdef __cplusplus
+
 inline jbyte
 _Jv_GetStaticByteField (jclass, _Jv_Field* field)
 {
@@ -151,6 +158,18 @@
   return klass->field_count - klass->static_field_count;
 }
 
+extern inline jfieldID
+JvGetFirstStaticField (jclass klass)
+{
+  return &(klass->fields[0]);
+}
+
+extern inline jint
+JvNumStaticFields (jclass klass)
+{
+  return klass->static_field_count;
+}
+
 extern inline jboolean
 JvFieldIsRef (jfieldID field)
 {
@@ -164,6 +183,6 @@
 }
 #endif /* defined (__GCJ_CNI_H__) */
 
-#endif
+#endif /* __cplusplus */
 
 #endif /* __GCJ_FIELD_H */
Index: gcj/method.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/gcj/method.h,v
retrieving revision 1.3
diff -u -r1.3 method.h
--- method.h	2000/01/19 18:39:24	1.3
+++ method.h	2000/01/21 23:41:44
@@ -1,6 +1,6 @@
-// java-method.h - Header file for methodID instances.  -*- c++ -*-
+// method.h - Header file for methodID instances.  -*- c++ -*-
 
-/* Copyright (C) 1999  Red Hat, Inc.
+/* Copyright (C) 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -11,8 +11,10 @@
 #ifndef __GCJ_METHOD_H__
 #define __GCJ_METHOD_H__
 
+#include <java/lang/Class.h>
+
 extern inline jmethodID
-_Jv_FromReflectedMethod(java::lang::reflect::Method *method)
+_Jv_FromReflectedMethod (java::lang::reflect::Method *method)
 {
   return (jmethodID)
     ((char *) method->declaringClass->methods + method->offset);
Index: include/jni.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/include/jni.h,v
retrieving revision 1.4
diff -u -r1.4 jni.h
--- jni.h	2000/01/19 18:39:25	1.4
+++ jni.h	2000/01/21 23:41:49
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -6,6 +6,11 @@
 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 details.  */
 
+/* Note: this file must be compilable by the C compiler (for now,
+   assuming GNU C is ok).  This means you must never use `//'
+   comments, and all C++-specific code must be conditional on
+   __cplusplus.  */
+
 #ifndef __GCJ_JNI_H__
 #define __GCJ_JNI_H__
 
@@ -14,12 +19,16 @@
 
 #ifdef __cplusplus
 
-// This is wrong, because it pollutes the name-space too much!
+/* This is wrong, because it pollutes the name-space too much! */
 #include <gcj/javaprims.h>
 
 typedef struct _Jv_JNIEnv JNIEnv;
-#else
 
+#define JNI_TRUE true
+#define JNI_FALSE false
+
+#else /* __cplusplus */
+
 typedef int    jbyte  __attribute__((__mode__(__QI__)));
 typedef int    jshort __attribute__((__mode__(__HI__)));
 typedef int    jint   __attribute__((__mode__(__SI__)));
@@ -30,20 +39,51 @@
 typedef double jdouble;
 typedef jint jsize;
 
+typedef void *jobject;
+typedef jobject jclass;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jobject jthrowable;
+typedef jobject jobjectArray;
+typedef jobject jbyteArray;
+typedef jobject jshortArray;
+typedef jobject jintArray;
+typedef jobject jlongArray;
+typedef jobject jbooleanArray;
+typedef jobject jcharArray;
+typedef jobject jfloatArray;
+typedef jobject jdoubleArray;
+
+/* Dummy defines.  */
+typedef void *jfieldID;
+typedef void *jmethodID;
+
 typedef const struct JNINativeInterface *JNIEnv;
-#endif
+
+#define JNI_TRUE 1
+#define JNI_TRUE 0
+
+#endif /* __cplusplus */
+
+/* Version numbers.  */
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+
+/* Used when releasing array elements.  */
+#define JNI_COMMIT 1
+#define JNI_ABORT  2
 
 typedef union jvalue
 {
   jboolean z;
   jbyte    b;
   jchar    c;
-  jshort  s;
-  jint    i;
+  jshort   s;
+  jint     i;
   jlong    j;
-  jfloat  f;
+  jfloat   f;
   jdouble  d;
-  jobject l;
+  jobject  l;
 } jvalue;
 
 typedef void * (*_Jv_func)(...);
@@ -54,7 +94,7 @@
   _Jv_func reserved1;
   _Jv_func reserved2;
   _Jv_func reserved3;
-  _Jv_func GetVersion;
+  jint     (*GetVersion)                   (JNIEnv*);
   _Jv_func DefineClass;
   _Jv_func FindClass;
   _Jv_func reserved4;
@@ -64,233 +104,415 @@
   jboolean (*IsAssignableFrom)             (JNIEnv*, jclass, jclass);
   _Jv_func reserved7;
   jint     (*Throw)                        (JNIEnv*, jthrowable);
-  _Jv_func ThrowNew;
-  _Jv_func ExceptionOccurred;
-  _Jv_func ExceptionDescribe;
-  _Jv_func ExceptionClear;
-  _Jv_func FatalError;
+  jint     (*ThrowNew)                     (JNIEnv*, jclass, const char *);
+  jthrowable (*ExceptionOccurred)          (JNIEnv *);
+  void     (*ExceptionDescribe)            (JNIEnv *);
+  void     (*ExceptionClear)               (JNIEnv *);
+  void     (*FatalError)                   (JNIEnv *, const char *);
   _Jv_func reserved8;
   _Jv_func reserved9;
   _Jv_func NewGlobalRef;
   _Jv_func DeleteGlobalRef;
   _Jv_func DeleteLocalRef;
-  _Jv_func IsSameObject;
+  jboolean (*IsSameObject)                 (JNIEnv *, jobject, jobject);
   _Jv_func reserved10;
   _Jv_func reserved11;
-  _Jv_func AllocObject;
-  _Jv_func NewObject;
-  _Jv_func NewObjectV;
-  _Jv_func NewObjectA;
-  _Jv_func GetObjectClass;
-  _Jv_func IsInstanceOf;
-  _Jv_func GetMethodID;
-  _Jv_func CallObjectMethod;
-  _Jv_func CallObjectMethodV;
-  _Jv_func CallObjectMethodA;
-  _Jv_func CallBooleanMethod;
-  _Jv_func CallBooleanMethodV;
-  _Jv_func CallBooleanMethodA;
-  _Jv_func CallByteMethod;
-  _Jv_func CallByteMethodV;
-  _Jv_func CallByteMethodA;
-  _Jv_func CallCharMethod;
-  _Jv_func CallCharMethodV;
-  _Jv_func CallCharMethodA;
-  _Jv_func CallShortMethod;
-  _Jv_func CallShortMethodV;
-  _Jv_func CallShortMethodA;
-  _Jv_func CallIntMethod;
-  _Jv_func CallIntMethodV;
-  _Jv_func CallIntMethodA;
-  _Jv_func CallLongMethod;
-  _Jv_func CallLongMethodV;
-  _Jv_func CallLongMethodA;
-  _Jv_func CallFloatMethod;
-  _Jv_func CallFloatMethodV;
-  _Jv_func CallFloatMethodA;
-  _Jv_func CallDoubleMethod;
-  _Jv_func CallDoubleMethodV;
-  _Jv_func CallDoubleMethodA;
-  _Jv_func CallVoidMethod;
-  _Jv_func CallVoidMethodV;
-  _Jv_func CallVoidMethodA;
-  _Jv_func CallNonvirtualObjectMethod;
-  _Jv_func CallNonvirtualObjectMethodV;
-  _Jv_func CallNonvirtualObjectMethodA;
-  jboolean (*CallNonvirtualBooleanMethod)  (JNIEnv*, jobject, jclass, jmethodID, ...);
-  jboolean (*CallNonvirtualBooleanMethodV) (JNIEnv*, jobject, jclass, jmethodID, _Jv_va_list);
-  jboolean (*CallNonvirtualBooleanMethodA) (JNIEnv*, jobject, jclass, jmethodID, jvalue*);
-  _Jv_func CallNonvirtualByteMethod;
-  _Jv_func CallNonvirtualByteMethodV;
-  _Jv_func CallNonvirtualByteMethodA;
-  _Jv_func CallNonvirtualCharMethod;
-  _Jv_func CallNonvirtualCharMethodV;
-  _Jv_func CallNonvirtualCharMethodA;
-  _Jv_func CallNonvirtualShortMethod;
-  _Jv_func CallNonvirtualShortMethodV;
-  _Jv_func CallNonvirtualShortMethodA;
-  _Jv_func CallNonvirtualIntMethod;
-  _Jv_func CallNonvirtualIntMethodV;
-  _Jv_func CallNonvirtualIntMethodA;
-  _Jv_func CallNonvirtualLongMethod;
-  _Jv_func CallNonvirtualLongMethodV;
-  _Jv_func CallNonvirtualLongMethodA;
-  _Jv_func CallNonvirtualFloatMethod;
-  _Jv_func CallNonvirtualFloatMethodV;
-  _Jv_func CallNonvirtualFloatMethodA;
-  _Jv_func CallNonvirtualDoubleMethod;
-  jdouble  (*CallNonvirtualDoubleMethodV)  (JNIEnv*, jobject, jclass, jmethodID, _Jv_va_list);
-  _Jv_func CallNonvirtualDoubleMethodA;
-  _Jv_func CallNonvirtualVoidMethod;
-  _Jv_func CallNonvirtualVoidMethodV;
-  _Jv_func CallNonvirtualVoidMethodA;
-  _Jv_func GetFieldID;
-  jobject  (*GetObjectField)               (JNIEnv*, jobject, jfieldID);
-  jboolean (*GetBooleanField)              (JNIEnv*, jobject, jfieldID);
-  jbyte    (*GetByteField)                 (JNIEnv*, jobject, jfieldID);
-  jchar    (*GetCharField)                 (JNIEnv*, jobject, jfieldID);
-  jshort   (*GetShortField)                (JNIEnv*, jobject, jfieldID);
-  jint     (*GetIntField)                  (JNIEnv*, jobject, jfieldID);
-  jlong    (*GetLongField)                 (JNIEnv*, jobject, jfieldID);
-  jfloat   (*GetFloatField)                (JNIEnv*, jobject, jfieldID);
-  jdouble  (*GetDoubleField)               (JNIEnv*, jobject, jfieldID);
-  _Jv_func SetObjectField;
-  _Jv_func SetBooleanField;
-  _Jv_func SetByteField;
-  _Jv_func SetCharField;
-  _Jv_func SetShortField;
-  _Jv_func SetIntField;
-  _Jv_func SetLongField;
-  _Jv_func SetFloatField;
-  _Jv_func SetDoubleField;
-  _Jv_func GetStaticMethodID;
-  _Jv_func CallStaticObjectMethod;
-  _Jv_func CallStaticObjectMethodV;
-  _Jv_func CallStaticObjectMethodA;
-  _Jv_func CallStaticBooleanMethod;
-  _Jv_func CallStaticBooleanMethodV;
-  _Jv_func CallStaticBooleanMethodA;
-  _Jv_func CallStaticByteMethod;
-  _Jv_func CallStaticByteMethodV;
-  _Jv_func CallStaticByteMethodA;
-  _Jv_func CallStaticCharMethod;
-  _Jv_func CallStaticCharMethodV;
-  _Jv_func CallStaticCharMethodA;
-  _Jv_func CallStaticShortMethod;
-  _Jv_func CallStaticShortMethodV;
-  _Jv_func CallStaticShortMethodA;
-  _Jv_func CallStaticIntMethod;
-  _Jv_func CallStaticIntMethodV;
-  _Jv_func CallStaticIntMethodA;
-  _Jv_func CallStaticLongMethod;
-  _Jv_func CallStaticLongMethodV;
-  _Jv_func CallStaticLongMethodA;
-  _Jv_func CallStaticFloatMethod;
-  _Jv_func CallStaticFloatMethodV;
-  _Jv_func CallStaticFloatMethodA;
-  _Jv_func CallStaticDoubleMethod;
-  _Jv_func CallStaticDoubleMethodV;
-  _Jv_func CallStaticDoubleMethodA;
-  _Jv_func CallStaticVoidMethod;
-  _Jv_func CallStaticVoidMethodV;
-  _Jv_func CallStaticVoidMethodA;
-  _Jv_func GetStaticFieldID;
-  _Jv_func GetStaticObjectField;
-  _Jv_func GetStaticBooleanField;
-  _Jv_func GetStaticByteField;
-  _Jv_func GetStaticCharField;
-  _Jv_func GetStaticShortField;
-  _Jv_func GetStaticIntField;
-  _Jv_func GetStaticLongField;
-  _Jv_func GetStaticFloatField;
-  _Jv_func GetStaticDoubleField;
-  _Jv_func SetStaticObjectField;
-  _Jv_func SetStaticBooleanField;
-  _Jv_func SetStaticByteField;
-  _Jv_func SetStaticCharField;
-  _Jv_func SetStaticShortField;
-  _Jv_func SetStaticIntField;
-  _Jv_func SetStaticLongField;
-  _Jv_func SetStaticFloatField;
-  _Jv_func SetStaticDoubleField;
-  _Jv_func NewString;
-  jint     (*GetStringLength)              (JNIEnv*, jstring);
-  _Jv_func GetStringChars;
-  _Jv_func ReleaseStringChars;
-  _Jv_func NewStringUTF;
-  _Jv_func GetStringUTFLength;
-  _Jv_func GetStringUTFChars;
-  _Jv_func ReleaseStringUTFChars;
-  _Jv_func GetArrayLength;
-  _Jv_func NewObjectArray;
-  _Jv_func GetObjectArrayElement;
-  _Jv_func SetObjectArrayElement;
-  _Jv_func NewBooleanArray;
-  _Jv_func NewByteArray;
-  _Jv_func NewCharArray;
-  _Jv_func NewShortArray;
-  _Jv_func NewIntArray;
-  _Jv_func NewLongArray;
-  _Jv_func NewFloatArray;
-  _Jv_func NewDoubleArray;
-  _Jv_func GetBooleanArrayElements;
-  _Jv_func GetByteArrayElements;
-  _Jv_func GetCharArrayElements;
-  _Jv_func GetShortArrayElements;
-  _Jv_func GetIntArrayElements;
-  _Jv_func GetLongArrayElements;
-  _Jv_func GetFloatArrayElements;
-  _Jv_func GetDoubleArrayElements;
-  _Jv_func ReleaseBooleanArrayElements;
-  _Jv_func ReleaseByteArrayElements;
-  _Jv_func ReleaseCharArrayElements;
-  _Jv_func ReleaseShortArrayElements;
-  _Jv_func ReleaseIntArrayElements;
-  _Jv_func ReleaseLongArrayElements;
-  _Jv_func ReleaseFloatArrayElements;
-  _Jv_func ReleaseDoubleArrayElements;
-  _Jv_func GetBooleanArrayRegion;
-  _Jv_func GetByteArrayRegion;
-  _Jv_func GetCharArrayRegion;
-  _Jv_func GetShortArrayRegion;
-  _Jv_func GetIntArrayRegion;
-  _Jv_func GetLongArrayRegion;
-  _Jv_func GetFloatArrayRegion;
-  _Jv_func GetDoubleArrayRegion;
-  _Jv_func SetBooleanArrayRegion;
-  _Jv_func SetByteArrayRegion;
-  _Jv_func SetCharArrayRegion;
-  _Jv_func SetShortArrayRegion;
-  _Jv_func SetIntArrayRegion;
-  _Jv_func SetLongArrayRegion;
-  _Jv_func SetFloatArrayRegion;
-  _Jv_func SetDoubleArrayRegion;
+
+  jobject  (*AllocObject)                  (JNIEnv *, jclass);
+  jobject (*NewObject)			   (JNIEnv *, jclass, jmethodID, ...);
+  jobject (*NewObjectV)			   (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jobject (*NewObjectA)			   (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+
+  jclass   (*GetObjectClass)               (JNIEnv *, jobject);
+  jboolean (*IsInstanceOf)                 (JNIEnv *, jobject, jclass);
+  jmethodID (*GetMethodID)                 (JNIEnv *, jclass, const char *,
+					    const char *);
+
+  jobject 	(*CallObjectMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jobject 	(*CallObjectMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jobject 	(*CallObjectMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jboolean 	(*CallBooleanMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jboolean 	(*CallBooleanMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jboolean 	(*CallBooleanMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jbyte 	(*CallByteMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jbyte 	(*CallByteMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jbyte 	(*CallByteMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jchar 	(*CallCharMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jchar 	(*CallCharMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jchar 	(*CallCharMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jshort 	(*CallShortMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jshort 	(*CallShortMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jshort 	(*CallShortMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jint 		(*CallIntMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jint 		(*CallIntMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jint 		(*CallIntMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jlong 	(*CallLongMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jlong 	(*CallLongMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jlong 	(*CallLongMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jfloat 	(*CallFloatMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jfloat 	(*CallFloatMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jfloat 	(*CallFloatMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  jdouble 	(*CallDoubleMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  jdouble 	(*CallDoubleMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  jdouble 	(*CallDoubleMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+  void  	(*CallVoidMethod)	   (JNIEnv *, jobject, jmethodID,
+					    ...);
+  void  	(*CallVoidMethodV)	   (JNIEnv *, jobject, jmethodID,
+					    _Jv_va_list);
+  void  	(*CallVoidMethodA)	   (JNIEnv *, jobject, jmethodID,
+					    jvalue *);
+
+  jobject   (*CallNonvirtualObjectMethod)  (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jobject   (*CallNonvirtualObjectMethodV) (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jobject   (*CallNonvirtualObjectMethodA) (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  jboolean  (*CallNonvirtualBooleanMethod) (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jboolean  (*CallNonvirtualBooleanMethodV) (JNIEnv *, jobject, jclass,
+					     jmethodID, _Jv_va_list);
+  jboolean  (*CallNonvirtualBooleanMethodA) (JNIEnv *, jobject, jclass,
+					     jmethodID, jvalue *);
+  jbyte     (*CallNonvirtualByteMethod)	   (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jbyte     (*CallNonvirtualByteMethodV)   (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jbyte     (*CallNonvirtualByteMethodA)   (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  jchar     (*CallNonvirtualCharMethod)	   (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jchar     (*CallNonvirtualCharMethodV)   (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jchar     (*CallNonvirtualCharMethodA)   (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  jshort    (*CallNonvirtualShortMethod)   (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jshort    (*CallNonvirtualShortMethodV)  (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jshort    (*CallNonvirtualShortMethodA)  (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  jint 	    (*CallNonvirtualIntMethod)	   (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jint 	    (*CallNonvirtualIntMethodV)	   (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jint 	    (*CallNonvirtualIntMethodA)	   (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  jlong     (*CallNonvirtualLongMethod)	   (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jlong     (*CallNonvirtualLongMethodV)   (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jlong     (*CallNonvirtualLongMethodA)   (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  jfloat    (*CallNonvirtualFloatMethod)   (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jfloat    (*CallNonvirtualFloatMethodV)  (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jfloat    (*CallNonvirtualFloatMethodA)  (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  jdouble   (*CallNonvirtualDoubleMethod)  (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  jdouble   (*CallNonvirtualDoubleMethodV) (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  jdouble   (*CallNonvirtualDoubleMethodA) (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+  void      (*CallNonvirtualVoidMethod)	   (JNIEnv *, jobject, jclass,
+					    jmethodID, ...);
+  void      (*CallNonvirtualVoidMethodV)   (JNIEnv *, jobject, jclass,
+					    jmethodID, _Jv_va_list);
+  void      (*CallNonvirtualVoidMethodA)   (JNIEnv *, jobject, jclass,
+					    jmethodID, jvalue *);
+
+  jfieldID      (*GetFieldID)              (JNIEnv *, jclass, const char *,
+					    const char *);
+
+  jobject  (*GetObjectField)               (JNIEnv *, jobject, jfieldID);
+  jboolean (*GetBooleanField)              (JNIEnv *, jobject, jfieldID);
+  jbyte    (*GetByteField)                 (JNIEnv *, jobject, jfieldID);
+  jchar    (*GetCharField)                 (JNIEnv *, jobject, jfieldID);
+  jshort   (*GetShortField)                (JNIEnv *, jobject, jfieldID);
+  jint     (*GetIntField)                  (JNIEnv *, jobject, jfieldID);
+  jlong    (*GetLongField)                 (JNIEnv *, jobject, jfieldID);
+  jfloat   (*GetFloatField)                (JNIEnv *, jobject, jfieldID);
+  jdouble  (*GetDoubleField)               (JNIEnv *, jobject, jfieldID);
+
+  void		(*SetObjectField)	   (JNIEnv *, jobject,
+					    jfieldID, jobject);
+  void		(*SetBooleanField)	   (JNIEnv *, jobject,
+					    jfieldID, jboolean);
+  void		(*SetByteField)		   (JNIEnv *, jobject,
+					    jfieldID, jbyte);
+  void		(*SetCharField)		   (JNIEnv *, jobject,
+					    jfieldID, jchar);
+  void		(*SetShortField)	   (JNIEnv *, jobject,
+					    jfieldID, jshort);
+  void		(*SetIntField)		   (JNIEnv *, jobject,
+					    jfieldID, jint);
+  void		(*SetLongField)		   (JNIEnv *, jobject,
+					    jfieldID, jlong);
+  void		(*SetFloatField)	   (JNIEnv *, jobject,
+					    jfieldID, jfloat);
+  void		(*SetDoubleField)	   (JNIEnv *, jobject,
+					    jfieldID, jdouble);
+
+  jmethodID (*GetStaticMethodID)           (JNIEnv *, jclass, const char *,
+					    const char *);
+
+  jobject 	(*CallStaticObjectMethod)  (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jobject 	(*CallStaticObjectMethodV) (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jobject 	(*CallStaticObjectMethodA) (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  jboolean 	(*CallStaticBooleanMethod) (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jboolean 	(*CallStaticBooleanMethodV) (JNIEnv *, jclass, jmethodID,
+					     _Jv_va_list);
+  jboolean 	(*CallStaticBooleanMethodA) (JNIEnv *, jclass, jmethodID,
+					     jvalue *);
+  jbyte 	(*CallStaticByteMethod)    (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jbyte 	(*CallStaticByteMethodV)   (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jbyte 	(*CallStaticByteMethodA)   (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  jchar 	(*CallStaticCharMethod)    (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jchar 	(*CallStaticCharMethodV)   (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jchar 	(*CallStaticCharMethodA)   (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  jshort 	(*CallStaticShortMethod)   (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jshort 	(*CallStaticShortMethodV)  (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jshort 	(*CallStaticShortMethodA)  (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  jint 		(*CallStaticIntMethod) 	   (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jint 		(*CallStaticIntMethodV)    (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jint 		(*CallStaticIntMethodA)    (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  jlong 	(*CallStaticLongMethod)    (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jlong 	(*CallStaticLongMethodV)   (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jlong 	(*CallStaticLongMethodA)   (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  jfloat 	(*CallStaticFloatMethod)   (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jfloat 	(*CallStaticFloatMethodV)  (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jfloat 	(*CallStaticFloatMethodA)  (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  jdouble 	(*CallStaticDoubleMethod)  (JNIEnv *, jclass, jmethodID,
+					    ...);
+  jdouble 	(*CallStaticDoubleMethodV) (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  jdouble 	(*CallStaticDoubleMethodA) (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+  void  	(*CallStaticVoidMethod)    (JNIEnv *, jclass, jmethodID,
+					    ...);
+  void  	(*CallStaticVoidMethodV)   (JNIEnv *, jclass, jmethodID,
+					    _Jv_va_list);
+  void  	(*CallStaticVoidMethodA)   (JNIEnv *, jclass, jmethodID,
+					    jvalue *);
+
+  jfieldID      (*GetStaticFieldID)        (JNIEnv *, jclass, const char *,
+					    const char *);
+
+  jobject	(*GetStaticObjectField)	   (JNIEnv *, jclass, jfieldID);
+  jboolean	(*GetStaticBooleanField)   (JNIEnv *, jclass, jfieldID);
+  jbyte		(*GetStaticByteField)	   (JNIEnv *, jclass, jfieldID);
+  jchar		(*GetStaticCharField)	   (JNIEnv *, jclass, jfieldID);
+  jshort	(*GetStaticShortField)	   (JNIEnv *, jclass, jfieldID);
+  jint		(*GetStaticIntField)	   (JNIEnv *, jclass, jfieldID);
+  jlong		(*GetStaticLongField)	   (JNIEnv *, jclass, jfieldID);
+  jfloat	(*GetStaticFloatField)	   (JNIEnv *, jclass, jfieldID);
+  jdouble	(*GetStaticDoubleField)	   (JNIEnv *, jclass, jfieldID);
+
+  void 		(*SetStaticObjectField)	   (JNIEnv *, jclass,
+					    jfieldID, jobject);
+  void 		(*SetStaticBooleanField)   (JNIEnv *, jclass,
+					    jfieldID, jboolean);
+  void 		(*SetStaticByteField)	   (JNIEnv *, jclass,
+					    jfieldID, jbyte);
+  void 		(*SetStaticCharField)	   (JNIEnv *, jclass,
+					    jfieldID, jchar);
+  void 		(*SetStaticShortField)	   (JNIEnv *, jclass,
+					    jfieldID, jshort);
+  void 		(*SetStaticIntField)	   (JNIEnv *, jclass,
+					    jfieldID, jint);
+  void 		(*SetStaticLongField)	   (JNIEnv *, jclass,
+					    jfieldID, jlong);
+  void 		(*SetStaticFloatField)	   (JNIEnv *, jclass,
+					    jfieldID, jfloat);
+  void 		(*SetStaticDoubleField)	   (JNIEnv *, jclass,
+					    jfieldID, jdouble);
+
+  jstring  (*NewString)                    (JNIEnv *, const jchar *, jsize);
+  jint     (*GetStringLength)              (JNIEnv *, jstring);
+  const jchar * (*GetStringChars)          (JNIEnv *, jstring, jboolean *);
+  void     (*ReleaseStringChars)           (JNIEnv *, jstring, const jchar *);
+  jstring  (*NewStringUTF)                 (JNIEnv *, const char *);
+  jsize    (*GetStringUTFLength)           (JNIEnv *, jstring);
+  const char * (*GetStringUTFChars)        (JNIEnv *, jstring, jboolean *);
+  void     (*ReleaseStringUTFChars)        (JNIEnv *, jstring, const char *);
+  jsize    (*GetArrayLength)               (JNIEnv *, jarray);
+  jarray   (*NewObjectArray)               (JNIEnv *, jsize, jclass, jobject);
+  jobject  (*GetObjectArrayElement)        (JNIEnv *, jobjectArray, jsize);
+  void     (*SetObjectArrayElement)        (JNIEnv *, jobjectArray, jsize,
+					    jobject);
+
+  jbooleanArray (*NewBooleanArray)	   (JNIEnv *, jsize);
+  jbyteArray    (*NewByteArray)		   (JNIEnv *, jsize);
+  jcharArray    (*NewCharArray)		   (JNIEnv *, jsize);
+  jshortArray   (*NewShortArray)	   (JNIEnv *, jsize);
+  jintArray     (*NewIntArray)		   (JNIEnv *, jsize);
+  jlongArray    (*NewLongArray)		   (JNIEnv *, jsize);
+  jfloatArray   (*NewFloatArray)	   (JNIEnv *, jsize);
+  jdoubleArray  (*NewDoubleArray)	   (JNIEnv *, jsize);
+
+  jboolean *	(*GetBooleanArrayElements) (JNIEnv *, jbooleanArray,
+					    jboolean *);
+  jbyte *	(*GetByteArrayElements)	   (JNIEnv *, jbyteArray,
+					    jboolean *);
+  jchar *	(*GetCharArrayElements)	   (JNIEnv *, jcharArray,
+					    jboolean *);
+  jshort *	(*GetShortArrayElements)   (JNIEnv *, jshortArray,
+					    jboolean *);
+  jint *	(*GetIntArrayElements)	   (JNIEnv *, jintArray,
+					    jboolean *);
+  jlong *	(*GetLongArrayElements)	   (JNIEnv *, jlongArray,
+					    jboolean *);
+  jfloat *	(*GetFloatArrayElements)   (JNIEnv *, jfloatArray,
+					    jboolean *);
+  jdouble *	(*GetDoubleArrayElements)  (JNIEnv *, jdoubleArray,
+					    jboolean *);
+
+  void		(*ReleaseBooleanArrayElements) (JNIEnv *, jbooleanArray,
+						jboolean *, jint);
+  void		(*ReleaseByteArrayElements)    (JNIEnv *, jbyteArray,
+					        jbyte *, jint);
+  void		(*ReleaseCharArrayElements)    (JNIEnv *, jcharArray,
+						jchar *, jint);
+  void		(*ReleaseShortArrayElements)   (JNIEnv *, jshortArray,
+						jshort *, jint);
+  void		(*ReleaseIntArrayElements)     (JNIEnv *, jintArray,
+						jint *, jint);
+  void		(*ReleaseLongArrayElements)    (JNIEnv *, jlongArray,
+						jlong *, jint);
+  void		(*ReleaseFloatArrayElements)   (JNIEnv *, jfloatArray,
+						jfloat *, jint);
+  void		(*ReleaseDoubleArrayElements)  (JNIEnv *, jdoubleArray,
+						jdouble *, jint);
+
+  void 		(*GetBooleanArrayRegion)   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*GetByteArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*GetCharArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*GetShortArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*GetIntArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*GetLongArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*GetFloatArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*GetDoubleArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+
+  void 		(*SetBooleanArrayRegion)   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*SetByteArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*SetCharArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*SetShortArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*SetIntArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*SetLongArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*SetFloatArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+  void 		(*SetDoubleArrayRegion)	   (JNIEnv *, jbooleanArray,
+					    jsize, jsize, jboolean *);
+
   _Jv_func RegisterNatives;
   _Jv_func UnregisterNatives;
-  _Jv_func MonitorEnter;
-  _Jv_func MonitorExit;
+  jint     (*MonitorEnter)                 (JNIEnv *, jobject);
+  jint     (*MonitorExit)                  (JNIEnv *, jobject);
   _Jv_func GetJavaVM;
 };
 
+/* This structure is used when registering native methods.  */
+typedef struct
+{
+  char *name;
+  char *signature;
+  void *fnPtr;			/* Sigh.  */
+} JNINativeMethod;
+
 #ifdef __cplusplus
 
-struct _Jv_JNIEnv
+class _Jv_JNIEnv
 {
+public:
+  /* The method table.  */
   struct JNINativeInterface *p;
 
-  jclass GetSuperclass (jclass cl);
-  jsize GetStringLength (jstring str);
+private:
+  /* The current exception.  */
+  jthrowable ex;
+
+  /* This doesn't really protect the private contents, because anybody
+     can set this macro.  However, if they do set it then they at
+     least know they are doing something unportable.  */
+#ifdef GCJ_JV_JNIENV_FRIEND
+  GCJ_JV_JNIENV_FRIEND;
+#endif
 
-};
+public:
+  jclass GetSuperclass (jclass cl)
+  { return p->GetSuperclass (this, cl); }
 
-extern inline jclass
-_Jv_JNIEnv::GetSuperclass (jclass cl)
-{ return p->GetSuperclass (this, cl); }
-
-extern inline jsize
-_Jv_JNIEnv::GetStringLength (jstring str)
-{ return p->GetStringLength (this, str); }
+  jsize GetStringLength (jstring str)
+  { return p->GetStringLength (this, str); }
+};
 
-#endif
+#endif /* __cplusplus */
 
 #endif /* __GCJ_JNI_H__ */
Index: include/jvm.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/include/jvm.h,v
retrieving revision 1.11
diff -u -r1.11 jvm.h
--- jvm.h	2000/01/19 18:39:25	1.11
+++ jvm.h	2000/01/21 23:41:49
@@ -1,6 +1,6 @@
 // jvm.h - Header file for private implementation information. -*- c++ -*-
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -166,9 +166,20 @@
 				       jclass declaringClass,
 				       JArray<jclass> **arg_types_out,
 				       jclass *return_type_out);
-extern jobject _Jv_CallNonvirtualMethodA (jobject, jclass,
-					  jmethodID, jboolean,
-					  JArray<jclass> *, jobjectArray);
+
+extern jobject _Jv_CallAnyMethodA (jobject obj, jclass return_type,
+				   jmethodID meth, jboolean is_constructor,
+				   JArray<jclass> *parameter_types,
+				   jobjectArray args);
+
+union jvalue;
+extern jthrowable _Jv_CallAnyMethodA (jobject obj,
+				      jclass return_type,
+				      jmethodID meth,
+				      jboolean is_constructor,
+				      JArray<jclass> *parameter_types,
+				      jvalue *args,
+				      jvalue *result);
 
 extern jobject _Jv_NewMultiArray (jclass, jint ndims, jint* dims)
   __attribute__((__malloc__));
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Class.h,v
retrieving revision 1.12
diff -u -r1.12 Class.h
--- Class.h	2000/01/19 18:39:25	1.12
+++ Class.h	2000/01/21 23:41:54
@@ -60,6 +60,9 @@
   _Jv_Utf8Const *signature;
   unsigned short accflags;
   void *ncode;
+
+  _Jv_Method *getNextMethod ()
+  { return this + 1; }
 };
 
 #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
@@ -168,13 +171,19 @@
 
   friend jfieldID JvGetFirstInstanceField (jclass);
   friend jint JvNumInstanceFields (jclass);
+  friend jfieldID JvGetFirstStaticField (jclass);
+  friend jint JvNumStaticFields (jclass);
+
   friend jobject _Jv_AllocObject (jclass, jint);
   friend jobjectArray _Jv_NewObjectArray (jsize, jclass, jobject);
   friend jobject _Jv_NewPrimArray (jclass, jint);
   friend jobject _Jv_JNI_ToReflectedField (_Jv_JNIEnv *, jclass, jfieldID);
   friend jfieldID _Jv_FromReflectedField (java::lang::reflect::Field *);
+
   friend jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *);
   friend jmethodID _Jv_FromReflectedConstructor (java::lang::reflect::Constructor *);
+  friend jint JvNumMethods (jclass);
+  friend jmethodID JvGetFirstMethod (jclass);
 
   friend class _Jv_PrimClass;
 
@@ -256,5 +265,18 @@
   // initialization.
   java::lang::Thread *thread;
 };
+
+
+extern inline jint
+JvNumMethods (jclass klass)
+{
+  return klass->method_count;
+}
+
+extern inline jmethodID
+JvGetFirstMethod (jclass klass)
+{
+  return &klass->methods[0];
+}
 
 #endif /* __JAVA_LANG_CLASS_H__ */
Index: java/lang/reflect/natConstructor.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/reflect/natConstructor.cc,v
retrieving revision 1.2
diff -u -r1.2 natConstructor.cc
--- natConstructor.cc	2000/01/19 18:39:26	1.2
+++ natConstructor.cc	2000/01/21 23:42:02
@@ -48,6 +48,6 @@
   jmethodID meth = _Jv_FromReflectedConstructor (this);
   // In the constructor case the return type is the type of the
   // constructor.
-  return _Jv_CallNonvirtualMethodA (NULL, declaringClass, meth, true,
-				    parameter_types, args);
+  return _Jv_CallAnyMethodA (NULL, declaringClass, meth, true,
+			     parameter_types, args);
 }
Index: java/lang/reflect/natMethod.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/reflect/natMethod.cc,v
retrieving revision 1.7
diff -u -r1.7 natMethod.cc
--- natMethod.cc	2000/01/19 18:39:26	1.7
+++ natMethod.cc	2000/01/21 23:42:02
@@ -12,6 +12,7 @@
 
 #include <gcj/cni.h>
 #include <jvm.h>
+#include <jni.h>
 
 #include <java/lang/reflect/Method.h>
 #include <java/lang/reflect/Constructor.h>
@@ -187,8 +188,8 @@
       meth = _Jv_LookupDeclaredMethod (k, meth->name, meth->signature);
     }
 
-  return _Jv_CallNonvirtualMethodA (obj, return_type, meth, false,
-				    parameter_types, args);
+  return _Jv_CallAnyMethodA (obj, return_type, meth, false,
+			     parameter_types, args);
 }
 
 jint
@@ -311,23 +312,22 @@
 // functions.  It handles both Methods and Constructors, and it can
 // handle any return type.  In the Constructor case, the `obj'
 // argument is unused and should be NULL; also, the `return_type' is
-// the class that the constructor will construct.
-jobject
-_Jv_CallNonvirtualMethodA (jobject obj,
-			   jclass return_type,
-			   jmethodID meth,
-			   jboolean is_constructor,
-			   JArray<jclass> *parameter_types,
-			   jobjectArray args)
+// the class that the constructor will construct.  RESULT is a pointer
+// to a `jvalue' (see jni.h); for a void method this should be NULL.
+// This function returns an exception (if one was thrown), or NULL if
+// the call went ok.
+jthrowable
+_Jv_CallAnyMethodA (jobject obj,
+		    jclass return_type,
+		    jmethodID meth,
+		    jboolean is_constructor,
+		    JArray<jclass> *parameter_types,
+		    jvalue *args,
+		    jvalue *result)
 {
   JvAssert (! is_constructor || ! obj);
   JvAssert (! is_constructor || ! return_type);
 
-  // FIXME: access checks.
-
-  if (parameter_types->length != args->length)
-    JvThrow (new java::lang::IllegalArgumentException);
-
   // See whether call needs an object as the first argument.  A
   // constructor does need a `this' argument, but it is one we create.
   jboolean needs_this = false;
@@ -349,7 +349,6 @@
 					      * sizeof (ffi_type *));
 
   jclass *paramelts = elements (parameter_types);
-  jobject *argelts = elements (args);
 
   // FIXME: at some point the compiler is going to add extra arguments
   // to some functions.  In particular we are going to do this for
@@ -376,22 +375,11 @@
 
   for (int arg = 0; i < param_count; ++i, ++arg)
     {
-      jclass k = argelts[arg] ? argelts[arg]->getClass() : NULL;
-      argtypes[i] = get_ffi_type (k);
+      argtypes[i] = get_ffi_type (paramelts[arg]);
       if (paramelts[arg]->isPrimitive())
-	{
-	  if (! argelts[arg]
-	      || ! k
-	      || ! can_widen (k, paramelts[arg]))
-	    JvThrow (new java::lang::IllegalArgumentException);
-	  size += paramelts[arg]->size();
-	}
+	size += paramelts[arg]->size();
       else
-	{
-	  if (argelts[arg] && ! paramelts[arg]->isAssignableFrom (k))
-	    JvThrow (new java::lang::IllegalArgumentException);
-	  size += sizeof (jobject);
-	}
+	size += sizeof (jobject);
     }
 
   ffi_cif cif;
@@ -404,89 +392,162 @@
   char *p = (char *) alloca (size);
   void **values = (void **) alloca (param_count * sizeof (void *));
 
-#define COPY(Where, What, Type) \
-  do { \
-    Type val = (What); \
-    memcpy ((Where), &val, sizeof (Type)); \
-    values[i] = (Where); \
-    Where += sizeof (Type); \
-  } while (0)
-
   i = 0;
   if (needs_this)
     {
-      COPY (p, obj, jobject);
+      values[i] = p;
+      memcpy (p, &obj, sizeof (jobject));
+      p += sizeof (jobject);
       ++i;
     }
 
   for (int arg = 0; i < param_count; ++i, ++arg)
     {
-      java::lang::Number *num = (java::lang::Number *) argelts[arg];
-      if (paramelts[arg] == JvPrimClass (byte))
-	COPY (p, num->byteValue(), jbyte);
-      else if (paramelts[arg] == JvPrimClass (short))
-	COPY (p, num->shortValue(), jshort);
-      else if (paramelts[arg] == JvPrimClass (int))
-	COPY (p, num->intValue(), jint);
-      else if (paramelts[arg] == JvPrimClass (long))
-	COPY (p, num->longValue(), jlong);
-      else if (paramelts[arg] == JvPrimClass (float))
-	COPY (p, num->floatValue(), jfloat);
-      else if (paramelts[arg] == JvPrimClass (double))
-	COPY (p, num->doubleValue(), jdouble);
-      else if (paramelts[arg] == JvPrimClass (boolean))
-	COPY (p, ((java::lang::Boolean *) argelts[arg])->booleanValue(),
-	      jboolean);
-      else if (paramelts[arg] == JvPrimClass (char))
-	COPY (p, ((java::lang::Character *) argelts[arg])->charValue(), jchar);
+      int tsize;
+      if (paramelts[arg]->isPrimitive())
+	tsize = paramelts[arg]->size();
       else
-	{
-	  JvAssert (! paramelts[arg]->isPrimitive());
-	  COPY (p, argelts[arg], jobject);
-	}
+	tsize = sizeof (jobject);
+
+      // Copy appropriate bits from the jvalue into the ffi array.
+      // FIXME: we could do this copying all in one loop, above, by
+      // over-allocating a bit.
+      values[i] = p;
+      memcpy (p, &args[arg], tsize);
+      p += tsize;
     }
 
   // FIXME: initialize class here.
 
-  // Largest possible value.  Hopefully it is aligned!
-  jdouble ret_value;
   java::lang::Throwable *ex;
   using namespace java::lang;
   using namespace java::lang::reflect;
   ex = Method::hack_trampoline ((gnu::gcj::RawData *) &cif,
 				(gnu::gcj::RawData *) meth->ncode,
-				(gnu::gcj::RawData *) &ret_value,
+				(gnu::gcj::RawData *) result,
 				(gnu::gcj::RawData *) values);
 
+  if (ex)
+    // FIXME: this is wrong for JNI.  But if we just return the
+    // exception, then the non-JNI cases won't be able to distinguish
+    // it from exceptions we might generate ourselves.  Sigh.
+    ex = new InvocationTargetException (ex);
+
+  if (is_constructor)
+    result->l = obj;
+
+  return ex;
+}
+
+// This is another version of _Jv_CallAnyMethodA, but this one does
+// more checking and is used by the reflection (and not JNI) code.
+jobject
+_Jv_CallAnyMethodA (jobject obj,
+		    jclass return_type,
+		    jmethodID meth,
+		    jboolean is_constructor,
+		    JArray<jclass> *parameter_types,
+		    jobjectArray args)
+{
+  // FIXME: access checks.
+
+  if (parameter_types->length != args->length)
+    JvThrow (new java::lang::IllegalArgumentException);
+
+  int param_count = parameter_types->length;
+
+  jclass *paramelts = elements (parameter_types);
+  jobject *argelts = elements (args);
+  jvalue argvals[param_count];
+
+#define COPY(Where, What, Type) \
+  do { \
+    Type val = (What); \
+    memcpy ((Where), &val, sizeof (Type)); \
+  } while (0)
+
+  for (int i = 0; i < param_count; ++i)
+    {
+      jclass k = argelts[i] ? argelts[i]->getClass() : NULL;
+      if (paramelts[i]->isPrimitive())
+	{
+	  if (! argelts[i]
+	      || ! k
+	      || ! can_widen (k, paramelts[i]))
+	    JvThrow (new java::lang::IllegalArgumentException);
+	}
+      else
+	{
+	  if (argelts[i] && ! paramelts[i]->isAssignableFrom (k))
+	    JvThrow (new java::lang::IllegalArgumentException);
+	}
+
+      java::lang::Number *num = (java::lang::Number *) argelts[i];
+      if (paramelts[i] == JvPrimClass (byte))
+	COPY (&argvals[i], num->byteValue(), jbyte);
+      else if (paramelts[i] == JvPrimClass (short))
+	COPY (&argvals[i], num->shortValue(), jshort);
+      else if (paramelts[i] == JvPrimClass (int))
+	COPY (&argvals[i], num->intValue(), jint);
+      else if (paramelts[i] == JvPrimClass (long))
+	COPY (&argvals[i], num->longValue(), jlong);
+      else if (paramelts[i] == JvPrimClass (float))
+	COPY (&argvals[i], num->floatValue(), jfloat);
+      else if (paramelts[i] == JvPrimClass (double))
+	COPY (&argvals[i], num->doubleValue(), jdouble);
+      else if (paramelts[i] == JvPrimClass (boolean))
+	COPY (&argvals[i],
+	      ((java::lang::Boolean *) argelts[i])->booleanValue(),
+	      jboolean);
+      else if (paramelts[i] == JvPrimClass (char))
+	COPY (&argvals[i],
+	      ((java::lang::Character *) argelts[i])->charValue(),
+	      jchar);
+      else
+	{
+	  JvAssert (! paramelts[i]->isPrimitive());
+	  COPY (&argvals[i], argelts[i], jobject);
+	}
+    }
+
+  jvalue ret_value;
+  java::lang::Throwable *ex = _Jv_CallAnyMethodA (obj,
+						  return_type,
+						  meth,
+						  is_constructor,
+						  parameter_types,
+						  argvals,
+						  &ret_value);
+
   if (ex)
-    JvThrow (new InvocationTargetException (ex));
+    JvThrow (ex);
 
   jobject r;
-#define VAL(Wrapper, Type)  (new Wrapper (* (Type *) &ret_value))
+#define VAL(Wrapper, Field)  (new Wrapper (ret_value.Field))
   if (is_constructor)
-    r = obj;
-  else if (return_type == JvPrimClass (byte))
-    r = VAL (java::lang::Byte, jbyte);
+    r = ret_value.l;
+  else  if (return_type == JvPrimClass (byte))
+    r = VAL (java::lang::Byte, b);
   else if (return_type == JvPrimClass (short))
-    r = VAL (java::lang::Short, jshort);
+    r = VAL (java::lang::Short, s);
   else if (return_type == JvPrimClass (int))
-    r = VAL (java::lang::Integer, jint);
+    r = VAL (java::lang::Integer, i);
   else if (return_type == JvPrimClass (long))
-    r = VAL (java::lang::Long, jlong);
+    r = VAL (java::lang::Long, j);
   else if (return_type == JvPrimClass (float))
-    r = VAL (java::lang::Float, jfloat);
+    r = VAL (java::lang::Float, f);
   else if (return_type == JvPrimClass (double))
-    r = VAL (java::lang::Double, jdouble);
+    r = VAL (java::lang::Double, d);
   else if (return_type == JvPrimClass (boolean))
-    r = VAL (java::lang::Boolean, jboolean);
+    r = VAL (java::lang::Boolean, z);
   else if (return_type == JvPrimClass (char))
-    r = VAL (java::lang::Character, jchar);
+    r = VAL (java::lang::Character, c);
   else if (return_type == JvPrimClass (void))
     r = NULL;
   else
     {
       JvAssert (return_type == NULL || ! return_type->isPrimitive());
-      r = * (Object **) &ret_value;
+      r = ret_value.l;
     }
 
   return r;


More information about the Java-patches mailing list