This is the mail archive of the java-patches@sourceware.cygnus.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: use try...catch in CNI code


I just checked in a patch to g++ which makes `try...catch' work even
when catching or throwing Java exceptions.  As a result I'm checking
in this patch to libgcj.  This patch removes all the ugly Java
trampolines we used to need to handle exceptions.  It also adds
correct exception handling to JNI.

I didn't change all the _Jv_Throw calls.  However I recommend that we
stop using _Jv_Throw and instead just use `throw'.  Perhaps I'll
change the _Jv_Throw calls at some point.

2000-03-02  Tom Tromey  <tromey@cygnus.com>

	* include/java-interp.h: Don't include MethodInvocation.h.
	(class _Jv_InterpMethod): Don't make MethodInvocation a friend.
	* Makefile.in: Rebuilt.
	* Makefile.am (gnu/gcj/runtime/MethodInvocation.h): Removed.
	(ordinary_java_source_files): Don't mention
	MethodInvocation.java.
	* gnu/gcj/runtime/MethodInvocation.java: Removed.
	* interpret.cc (MethodInvocation::continue1): Removed.
	(run): Handle exceptions here.
	* java/lang/ClassLoader.java (defineClass1, defineClass2):
	Removed.
	* java/lang/natClassLoader.cc (defineClass0): Catch exceptions
	here.
	(defineClass2): Removed.

	* java/lang/reflect/Method.java (hack_trampoline, hack_call):
	Removed.
	* java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA): Catch
	exceptions here.
	(hack_call): Removed.

	* java/lang/Class.h (Class): Removed hackRunInitializers,
	hackTrampoline.
	* java/lang/natClass.cc (hackRunInitializers): Removed.
	(initializeClass): Catch exceptions here.
	Include ExceptionInInitializerError.h.
	* java/lang/Class.java (hackTrampoline, hackRunInitializers):
	Removed.

	* java/lang/Object.h (Object): Don't mention hack12_6.
	* java/lang/natObject.cc (_Jv_FinalizeObject): Catch exceptions
	here.
	* java/lang/Object.java (hack12_6): Removed.

	* java/lang/natThread.cc (run_): Renamed.  Catch exceptions here.
	(start): Use run_, not run__.
	* java/lang/Thread.java (run_): Renamed from run__; old run_
	removed.

	* jni.cc (_Jv_JNI_FindClass): Handle exceptions.
	(_Jv_JNI_EnsureLocalCapacity): Likewise.
	(_Jv_JNI_DefineClass): Likewise.
	(_Jv_JNI_ThrowNew): Likewise.
	(_Jv_JNI_AllocObject): Likewise.
	(_Jv_JNI_GetAnyMethodID): Likewise.
	(_Jv_JNI_CallAnyMethodV): Likewise.
	(_Jv_JNI_CallAnyMethodA): Likewise.
	(_Jv_JNI_CallAnyVoidMethodV): Likewise.
	(_Jv_JNI_CallAnyVoidMethodA): Likewise.
	(_Jv_JNI_GetAnyFieldID): Likewise.
	(_Jv_JNI_NewString): Likewise.
	(_Jv_JNI_NewStringUTF): Likewise.
	(_Jv_JNI_GetStringUTFChars): Likewise.
	(_Jv_JNI_NewObjectArray): Likewise.
	(_Jv_JNI_NewPrimitiveArray): Likewise.
	(_Jv_JNI_GetPrimitiveArrayRegion): Likewise.
	(_Jv_JNI_GetStringRegion): Likewise.
	(_Jv_JNI_GetStringUTFRegion): Likewise.
	(_Jv_JNI_SetPrimitiveArrayRegion): Likewise.
	(_Jv_JNI_MonitorEnter): Likewise.
	(_Jv_JNI_MonitorExit): Likewise.
	(_Jv_JNI_ToReflectedField): Likewise.
	(_Jv_JNI_ToReflectedMethod): Likewise.
	(_Jv_JNI_RegisterNatives): Likewise.
	(_Jv_JNI_AttachCurrentThread): Likewise.
	(_Jv_JNI_DestroyJavaVM): Likewise.

Tom

Index: Makefile.am
===================================================================
RCS file: /cvs/java/libgcj/libjava/Makefile.am,v
retrieving revision 1.48
diff -u -r1.48 Makefile.am
--- Makefile.am	2000/02/21 05:54:28	1.48
+++ Makefile.am	2000/03/02 20:12:59
@@ -267,11 +267,6 @@
 	    -friend 'java::lang::ClassLoader;' \
 	    $(basename $<)
 
-gnu/gcj/runtime/MethodInvocation.h: gnu/gcj/runtime/MethodInvocation.class libgcj.zip
-	$(GCJH) -classpath $(top_builddir) \
-	    -friend 'class _Jv_InterpMethod;' \
-	    $(basename $<)
-
 ## Headers we maintain by hand and which we want to install.
 extra_headers = java/lang/Object.h java/lang/Class.h
 
@@ -525,7 +520,6 @@
 gnu/gcj/io/DefaultMimeTypes.java \
 gnu/gcj/io/MimeTypes.java \
 gnu/gcj/jni/NativeThread.java \
-gnu/gcj/runtime/MethodInvocation.java \
 gnu/gcj/runtime/VMClassLoader.java \
 gnu/gcj/text/BaseBreakIterator.java \
 gnu/gcj/text/CharacterBreakIterator.java \
Index: interpret.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/interpret.cc,v
retrieving revision 1.12
diff -u -r1.12 interpret.cc
--- interpret.cc	2000/02/11 23:24:28	1.12
+++ interpret.cc	2000/03/02 20:13:06
@@ -33,20 +33,8 @@
 #include <java-insns.h>
 #include <java-signal.h>
 
-#ifndef INTERPRETER
+#ifdef INTERPRETER
 
-#include <gnu/gcj/runtime/MethodInvocation.h>
-
-/* This should never happen. */
-void 
-gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *,
-						gnu::gcj::RawData *)
-{
-  JvFail ("no interpreter");
-}
-
-#else
-
 #define ClassError _CL_Q34java4lang5Error
 extern java::lang::Class ClassError;
 
@@ -216,10 +204,17 @@
   memcpy ((void*) locals, (void*) args, args_raw_size);
 
  next_segment:
-  /* this will call the method _Jv_InterpMethod::continue0, see below */
-  jobject ex = 
-    gnu::gcj::runtime::MethodInvocation::continue0
-    ((gnu::gcj::RawData *)this, (gnu::gcj::RawData *)inv);
+
+  jobject ex = NULL;
+
+  try
+    {
+      continue1 (inv);
+    }
+  catch (java::lang::Throwable *ex2)
+    {
+      ex = ex2;
+    }
 
   if (ex == 0)			// no exception...
     {
@@ -280,7 +275,6 @@
 	default:
 	  throw_internal_error ("unknown return type");
 	}
-
     }
 
   /** handle an exception */
@@ -377,16 +371,6 @@
   _Jv_MonitorExit (sync);
 
   if (ex != 0) _Jv_Throw (ex);
-}
-
-/* this is the exception handler hack, for the interpreter */
-void 
-gnu::gcj::runtime::MethodInvocation::continue1 (gnu::gcj::RawData *meth,
-						gnu::gcj::RawData *inv)
-{
-  _Jv_InterpMethod           *meth0 = (_Jv_InterpMethod*)meth;
-  _Jv_InterpMethodInvocation *inv0  = (_Jv_InterpMethodInvocation*)inv;
-  meth0->continue1 (inv0);
 }
 
 /*
Index: jni.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/jni.cc,v
retrieving revision 1.23
diff -u -r1.23 jni.cc
--- jni.cc	2000/02/26 21:12:54	1.23
+++ jni.cc	2000/03/02 20:13:09
@@ -115,6 +115,7 @@
   using namespace java::lang;
   Integer *refcount = (Integer *) ref_table->get (obj);
   jint val = (refcount == NULL) ? 0 : refcount->intValue ();
+  // FIXME: what about out of memory error?
   ref_table->put (obj, new Integer (val + 1));
 }
 
@@ -131,6 +132,7 @@
   if (val == 0)
     ref_table->remove (obj);
   else
+    // FIXME: what about out of memory error?
     ref_table->put (obj, new Integer (val));
 }
 
@@ -180,13 +182,15 @@
   // size.  This isn't the most efficient thing, but for now we don't
   // care.  Note that _Jv_JNI_PushLocalFrame relies on this right now.
 
-  _Jv_JNI_LocalFrame *frame
-    = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
-						  + size * sizeof (jobject));
-  if (frame == NULL)
+  _Jv_JNI_LocalFrame *frame;
+  try
     {
-      // FIXME: exception processing.
-      env->ex = new java::lang::OutOfMemoryError;
+      frame = (_Jv_JNI_LocalFrame *) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame)
+						 + size * sizeof (jobject));
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
       return JNI_ERR;
     }
 
@@ -304,16 +308,24 @@
 _Jv_JNI_DefineClass (JNIEnv *env, jobject loader, 
 		     const jbyte *buf, jsize bufLen)
 {
-  jbyteArray bytes = JvNewByteArray (bufLen);
-  jbyte *elts = elements (bytes);
-  memcpy (elts, buf, bufLen * sizeof (jbyte));
-
-  java::lang::ClassLoader *l
-    = reinterpret_cast<java::lang::ClassLoader *> (loader);
-
-  // FIXME: exception processing.
-  jclass result = l->defineClass (bytes, 0, bufLen);
-  return (jclass) wrap_value (env, result);
+  try
+    {
+      jbyteArray bytes = JvNewByteArray (bufLen);
+
+      jbyte *elts = elements (bytes);
+      memcpy (elts, buf, bufLen * sizeof (jbyte));
+
+      java::lang::ClassLoader *l
+	= reinterpret_cast<java::lang::ClassLoader *> (loader);
+
+      jclass result = l->defineClass (bytes, 0, bufLen);
+      return (jclass) wrap_value (env, result);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+      return NULL;
+    }
 }
 
 static jclass
@@ -324,21 +336,30 @@
   char s[len + 1];
   for (int i = 0; i <= len; ++i)
     s[i] = (name[i] == '/') ? '.' : name[i];
-  jstring n = JvNewStringUTF (s);
 
-  java::lang::ClassLoader *loader;
-  if (env->klass == NULL)
+  jclass r = NULL;
+  try
     {
-      // FIXME: should use getBaseClassLoader, but we don't have that
-      // yet.
-      loader = java::lang::ClassLoader::getSystemClassLoader ();
-    }
-  else
-    loader = env->klass->getClassLoader ();
+      // This might throw an out of memory exception.
+      jstring n = JvNewStringUTF (s);
 
-  // FIXME: exception processing.
-  jclass r = loader->loadClass (n);
+      java::lang::ClassLoader *loader;
+      if (env->klass == NULL)
+	{
+	  // FIXME: should use getBaseClassLoader, but we don't have that
+	  // yet.
+	  loader = java::lang::ClassLoader::getSystemClassLoader ();
+	}
+      else
+	loader = env->klass->getClassLoader ();
 
+      r = loader->loadClass (n);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
+
   return (jclass) wrap_value (env, r);
 }
 
@@ -369,25 +390,33 @@
   using namespace java::lang::reflect;
 
   JvAssert ((&ThrowableClass)->isAssignableFrom (clazz));
+
+  int r = JNI_OK;
+  try
+    {
+      JArray<jclass> *argtypes
+	= (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
 
-  JArray<jclass> *argtypes
-    = (JArray<jclass> *) JvNewObjectArray (1, &ClassClass, NULL);
+      jclass *elts = elements (argtypes);
+      elts[0] = &StringClass;
 
-  jclass *elts = elements (argtypes);
-  elts[0] = &StringClass;
+      Constructor *cons = clazz->getConstructor (argtypes);
 
-  // FIXME: exception processing.
-  Constructor *cons = clazz->getConstructor (argtypes);
+      jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
+      jobject *velts = elements (values);
+      velts[0] = JvNewStringUTF (message);
 
-  jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
-  jobject *velts = elements (values);
-  velts[0] = JvNewStringUTF (message);
+      jobject obj = cons->newInstance (values);
 
-  // FIXME: exception processing.
-  jobject obj = cons->newInstance (values);
+      env->ex = reinterpret_cast<jthrowable> (obj);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+      r = JNI_ERR;
+    }
 
-  env->ex = reinterpret_cast<jthrowable> (obj);
-  return 0;
+  return r;
 }
 
 static jthrowable
@@ -435,14 +464,20 @@
   jobject obj = NULL;
   using namespace java::lang::reflect;
 
-  JvAssert (clazz && ! clazz->isArray ());
-  if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
-    env->ex = new java::lang::InstantiationException ();
-  else
+  try
+    {
+      JvAssert (clazz && ! clazz->isArray ());
+      if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
+	env->ex = new java::lang::InstantiationException ();
+      else
+	{
+	  // FIXME: will this work for String?
+	  obj = JvAllocObject (clazz);
+	}
+    }
+  catch (jthrowable t)
     {
-      // FIXME: exception processing.
-      // FIXME: will this work for String?
-      obj = JvAllocObject (clazz);
+      env->ex = t;
     }
 
   return wrap_value (env, obj);
@@ -472,36 +507,43 @@
 _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);
+  try
+    {
+      _Jv_InitClass (clazz);
 
-  JvAssert (! clazz->isPrimitive());
+      _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
+      _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
 
-  using namespace java::lang::reflect;
+      JvAssert (! clazz->isPrimitive());
 
-  while (clazz != NULL)
-    {
-      jint count = JvNumMethods (clazz);
-      jmethodID meth = JvGetFirstMethod (clazz);
+      using namespace java::lang::reflect;
 
-      for (jint i = 0; i < count; ++i)
+      while (clazz != NULL)
 	{
-	  if (((is_static && Modifier::isStatic (meth->accflags))
-	       || (! is_static && ! Modifier::isStatic (meth->accflags)))
-	      && _Jv_equalUtf8Consts (meth->name, name_u)
-	      && _Jv_equalUtf8Consts (meth->signature, sig_u))
-	    return meth;
+	  jint count = JvNumMethods (clazz);
+	  jmethodID meth = JvGetFirstMethod (clazz);
 
-	  meth = meth->getNextMethod();
+	  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 ();
 	}
 
-      clazz = clazz->getSuperclass ();
+      env->ex = new java::lang::NoSuchMethodError ();
     }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
 
-  env->ex = new java::lang::NoSuchMethodError ();
   return NULL;
 }
 
@@ -553,27 +595,36 @@
 
   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);
-
-  // For constructors we need to pass the Class we are instantiating.
-  if (style == constructor)
-    return_type = klass;
-
-  jvalue result;
-  jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
-				      style == constructor,
-				      arg_types, args, &result);
+
+  try
+    {
+      _Jv_GetTypesFromSignature (id, decl_class,
+				 &arg_types, &return_type);
+
+      jvalue args[arg_types->length];
+      array_from_valist (args, arg_types, vargs);
+
+      // For constructors we need to pass the Class we are instantiating.
+      if (style == constructor)
+	return_type = klass;
+
+      jvalue result;
+      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+					  style == constructor,
+					  arg_types, args, &result);
 
-  if (ex != NULL)
-    env->ex = ex;
+      if (ex != NULL)
+	env->ex = ex;
 
-  // We cheat a little here.  FIXME.
-  return wrap_value (env, * (T *) &result);
+      // We cheat a little here.  FIXME.
+      return wrap_value (env, * (T *) &result);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
+
+  return wrap_value (env, (T) 0);
 }
 
 template<typename T, invocation_type style>
@@ -604,24 +655,32 @@
 
   jclass return_type;
   JArray<jclass> *arg_types;
-  // FIXME: exception processing.
-  _Jv_GetTypesFromSignature (id, decl_class,
-			     &arg_types, &return_type);
-
-  // For constructors we need to pass the Class we are instantiating.
-  if (style == constructor)
-    return_type = klass;
-
-  jvalue result;
-  jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
-				      style == constructor,
-				      arg_types, args, &result);
+  try
+    {
+      _Jv_GetTypesFromSignature (id, decl_class,
+				 &arg_types, &return_type);
 
-  if (ex != NULL)
-    env->ex = ex;
+      // For constructors we need to pass the Class we are instantiating.
+      if (style == constructor)
+	return_type = klass;
 
-  // We cheat a little here.  FIXME.
-  return wrap_value (env, * (T *) &result);
+      jvalue result;
+      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+					  style == constructor,
+					  arg_types, args, &result);
+
+      if (ex != NULL)
+	env->ex = ex;
+
+      // We cheat a little here.  FIXME.
+      return wrap_value (env, * (T *) &result);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
+
+  return wrap_value (env, (T) 0);
 }
 
 template<invocation_type style>
@@ -637,23 +696,29 @@
 
   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);
-
-  // For constructors we need to pass the Class we are instantiating.
-  if (style == constructor)
-    return_type = klass;
-
-  jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
-				      style == constructor,
-				      arg_types, args, NULL);
+  try
+    {
+      _Jv_GetTypesFromSignature (id, decl_class,
+				 &arg_types, &return_type);
+
+      jvalue args[arg_types->length];
+      array_from_valist (args, arg_types, vargs);
+
+      // For constructors we need to pass the Class we are instantiating.
+      if (style == constructor)
+	return_type = klass;
 
-  if (ex != NULL)
-    env->ex = ex;
+      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+					  style == constructor,
+					  arg_types, args, NULL);
+
+      if (ex != NULL)
+	env->ex = ex;
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
 }
 
 template<invocation_type style>
@@ -681,16 +746,22 @@
 
   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);
+  try
+    {
+      _Jv_GetTypesFromSignature (id, decl_class,
+				 &arg_types, &return_type);
 
-  if (ex != NULL)
-    env->ex = ex;
+      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
+					  style == constructor,
+					  arg_types, args, NULL);
+
+      if (ex != NULL)
+	env->ex = ex;
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
 }
 
 // Functions with this signature are used to implement functions in
@@ -895,49 +966,55 @@
 _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
 		       const char *name, const char *sig)
 {
-  // FIXME: exception processing.
-  _Jv_InitClass (clazz);
+  try
+    {
+      _Jv_InitClass (clazz);
 
-  _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
+      _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
 
-  jclass field_class = NULL;
-  if (sig[0] == '[')
-    field_class = _Jv_FindClassFromSignature ((char *) sig, NULL);
-  else
-    {
-      _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) sig, -1);
-      field_class = _Jv_FindClass (sig_u, NULL);
-    }
+      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?
+      // FIXME: what if field_class == NULL?
 
-  while (clazz != NULL)
-    {
-      jint count = (is_static
-		    ? JvNumStaticFields (clazz)
-		    : JvNumInstanceFields (clazz));
-      jfieldID field = (is_static
-			? JvGetFirstStaticField (clazz)
-			: JvGetFirstInstanceField (clazz));
-      for (jint i = 0; i < count; ++i)
+      while (clazz != NULL)
 	{
-	  // The field is resolved as a side effect of class
-	  // initialization.
-	  JvAssert (field->isResolved ());
+	  jint count = (is_static
+			? JvNumStaticFields (clazz)
+			: JvNumInstanceFields (clazz));
+	  jfieldID field = (is_static
+			    ? JvGetFirstStaticField (clazz)
+			    : JvGetFirstInstanceField (clazz));
+	  for (jint i = 0; i < count; ++i)
+	    {
+	      // The field is resolved as a side effect of class
+	      // initialization.
+	      JvAssert (field->isResolved ());
+
+	      _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
 
-	  _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
+	      if (_Jv_equalUtf8Consts (f_name, a_name)
+		  && field->getClass() == field_class)
+		return field;
 
-	  if (_Jv_equalUtf8Consts (f_name, a_name)
-	      && field->getClass() == field_class)
-	    return field;
+	      field = field->getNextField ();
+	    }
 
-	  field = field->getNextField ();
+	  clazz = clazz->getSuperclass ();
 	}
 
-      clazz = clazz->getSuperclass ();
+      env->ex = new java::lang::NoSuchFieldError ();
     }
-
-  env->ex = new java::lang::NoSuchFieldError ();
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
   return NULL;
 }
 
@@ -960,9 +1037,16 @@
 static jstring
 _Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
 {
-  // FIXME: exception processing.
-  jstring r = _Jv_NewString (unichars, len);
-  return (jstring) wrap_value (env, r);
+  try
+    {
+      jstring r = _Jv_NewString (unichars, len);
+      return (jstring) wrap_value (env, r);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+      return NULL;
+    }
 }
 
 static jsize
@@ -990,9 +1074,16 @@
 static jstring
 _Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
 {
-  // FIXME: exception processing.
-  jstring result = JvNewStringUTF (bytes);
-  return (jstring) wrap_value (env, result);
+  try
+    {
+      jstring result = JvNewStringUTF (bytes);
+      return (jstring) wrap_value (env, result);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+      return NULL;
+    }
 }
 
 static jsize
@@ -1002,18 +1093,25 @@
 }
 
 static const char *
-_Jv_JNI_GetStringUTFChars (JNIEnv *, jstring string, jboolean *isCopy)
+_Jv_JNI_GetStringUTFChars (JNIEnv *env, jstring string, jboolean *isCopy)
 {
   jsize len = JvGetStringUTFLength (string);
-  // FIXME: exception processing.
-  char *r = (char *) _Jv_Malloc (len + 1);
-  JvGetStringUTFRegion (string, 0, len, r);
-  r[len] = '\0';
+  try
+    {
+      char *r = (char *) _Jv_Malloc (len + 1);
+      JvGetStringUTFRegion (string, 0, len, r);
+      r[len] = '\0';
 
-  if (isCopy)
-    *isCopy = true;
+      if (isCopy)
+	*isCopy = true;
 
-  return (const char *) r;
+      return (const char *) r;
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+      return NULL;
+    }
 }
 
 static void
@@ -1029,7 +1127,16 @@
   jchar *result = _Jv_GetStringChars (string);
   if (start < 0 || start > string->length ()
       || len < 0 || start + len > string->length ())
-    env->ex = new java::lang::StringIndexOutOfBoundsException ();
+    {
+      try
+	{
+	  env->ex = new java::lang::StringIndexOutOfBoundsException ();
+	}
+      catch (jthrowable t)
+	{
+	  env->ex = t;
+	}
+    }
   else
     memcpy (buf, &result[start], len * sizeof (jchar));
 }
@@ -1040,7 +1147,16 @@
 {
   if (start < 0 || start > str->length ()
       || len < 0 || start + len > str->length ())
-    env->ex = new java::lang::StringIndexOutOfBoundsException ();
+    {
+      try
+	{
+	  env->ex = new java::lang::StringIndexOutOfBoundsException ();
+	}
+      catch (jthrowable t)
+	{
+	  env->ex = t;
+	}
+    }
   else
     _Jv_GetStringUTFRegion (str, start, len, buf);
 }
@@ -1070,9 +1186,16 @@
 _Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
 			jobject init)
 {
-  // FIXME: exception processing.
-  jarray result = JvNewObjectArray (length, elementClass, init);
-  return (jarray) wrap_value (env, result);
+  try
+    {
+      jarray result = JvNewObjectArray (length, elementClass, init);
+      return (jarray) wrap_value (env, result);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+      return NULL;
+    }
 }
 
 static jobject
@@ -1083,21 +1206,34 @@
 }
 
 static void
-_Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
+_Jv_JNI_SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index,
 			       jobject value)
 {
-  // FIXME: exception processing.
-  _Jv_CheckArrayStore (array, value);
-  jobject *elts = elements (array);
-  elts[index] = value;
+  try
+    {
+      _Jv_CheckArrayStore (array, value);
+      jobject *elts = elements (array);
+      elts[index] = value;
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
 }
 
 template<typename T, jclass K>
 static JArray<T> *
 _Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
 {
-  // FIXME: exception processing.
-  return (JArray<T> *) wrap_value (env, _Jv_NewPrimArray (K, length));
+  try
+    {
+      return (JArray<T> *) wrap_value (env, _Jv_NewPrimArray (K, length));
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+      return NULL;
+    }
 }
 
 template<typename T>
@@ -1134,8 +1270,16 @@
 {
   if (start < 0 || len >= array->length || start + len >= array->length)
     {
-      // FIXME: index.
-      env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
+      try
+	{
+	  // FIXME: index.
+	  env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
+	}
+      catch (jthrowable t)
+	{
+	  // Could have thown out of memory error.
+	  env->ex = t;
+	}
     }
   else
     {
@@ -1151,8 +1295,15 @@
 {
   if (start < 0 || len >= array->length || start + len >= array->length)
     {
-      // FIXME: index.
-      env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
+      try
+	{
+	  // FIXME: index.
+	  env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
+	}
+      catch (jthrowable t)
+	{
+	  env->ex = t;
+	}
     }
   else
     {
@@ -1181,19 +1332,31 @@
 }
 
 static jint
-_Jv_JNI_MonitorEnter (JNIEnv *, jobject obj)
+_Jv_JNI_MonitorEnter (JNIEnv *env, jobject obj)
 {
-  // FIXME: exception processing.
-  jint r = _Jv_MonitorEnter (obj);
-  return r;
+  try
+    {
+      return _Jv_MonitorEnter (obj);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
+  return JNI_ERR;
 }
 
 static jint
-_Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
+_Jv_JNI_MonitorExit (JNIEnv *env, jobject obj)
 {
-  // FIXME: exception processing.
-  jint r = _Jv_MonitorExit (obj);
-  return r;
+  try
+    {
+      return _Jv_MonitorExit (obj);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
+  return JNI_ERR;
 }
 
 // JDK 1.2
@@ -1201,12 +1364,19 @@
 _Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
 			  jboolean)
 {
-  // FIXME: exception processing.
-  java::lang::reflect::Field *field = new java::lang::reflect::Field();
-  field->declaringClass = cls;
-  field->offset = (char*) fieldID - (char *) cls->fields;
-  field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
-  return wrap_value (env, field);
+  try
+    {
+      java::lang::reflect::Field *field = new java::lang::reflect::Field();
+      field->declaringClass = cls;
+      field->offset = (char*) fieldID - (char *) cls->fields;
+      field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
+      return wrap_value (env, field);
+    }
+  catch (jthrowable t)
+    {
+      env->ex = t;
+    }
+  return NULL;
 }
 
 // JDK 1.2
@@ -1228,21 +1398,29 @@
   // FIXME.
   static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
 
-  jobject result;
-  if (_Jv_equalUtf8Consts (id->name, init_name))
+  jobject result = NULL;
+
+  try
     {
-      // A constructor.
-      Constructor *cons = new Constructor ();
-      cons->offset = (char *) id - (char *) &klass->methods;
-      cons->declaringClass = klass;
-      result = cons;
+      if (_Jv_equalUtf8Consts (id->name, init_name))
+	{
+	  // A constructor.
+	  Constructor *cons = new Constructor ();
+	  cons->offset = (char *) id - (char *) &klass->methods;
+	  cons->declaringClass = klass;
+	  result = cons;
+	}
+      else
+	{
+	  Method *meth = new Method ();
+	  meth->offset = (char *) id - (char *) &klass->methods;
+	  meth->declaringClass = klass;
+	  result = meth;
+	}
     }
-  else
+  catch (jthrowable t)
     {
-      Method *meth = new Method ();
-      meth->offset = (char *) id - (char *) &klass->methods;
-      meth->declaringClass = klass;
-      result = meth;
+      env->ex = t;
     }
 
   return wrap_value (env, result);
@@ -1302,7 +1480,14 @@
       if (! found)
 	{
 	  jstring m = JvNewStringUTF (methods[j].name);
-	  _Jv_JNI_Throw (env, new java::lang::NoSuchMethodError (m));
+	  try
+	    {
+	      env->ex =new java::lang::NoSuchMethodError (m);
+	    }
+	  catch (jthrowable t)
+	    {
+	      env->ex = t;
+	    }
 	  return JNI_ERR;
 	}
     }
@@ -1545,7 +1730,14 @@
   // have been called simply to set the new JNIEnv.
   if (_Jv_ThreadCurrent () == NULL)
     {
-      (void) new gnu::gcj::jni::NativeThread (group, name);
+      try
+	{
+	  (void) new gnu::gcj::jni::NativeThread (group, name);
+	}
+      catch (jthrowable t)
+	{
+	  return JNI_ERR;
+	}
     }
   _Jv_SetCurrentJNIEnv (env);
 
@@ -1567,8 +1759,19 @@
   JNIEnv *env;
   if (_Jv_ThreadCurrent () != NULL)
     {
+      jstring main_name;
+      // This sucks.
+      try
+	{
+	  main_name = JvNewStringLatin1 ("main");
+	}
+      catch (jthrowable t)
+	{
+	  return JNI_ERR;
+	}
+
       jint r = _Jv_JNI_AttachCurrentThread (vm,
-					    JvNewStringLatin1 ("main"),
+					    main_name,
 					    reinterpret_cast<void **> (&env),
 					    NULL);
       if (r < 0)
Index: include/java-interp.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/include/java-interp.h,v
retrieving revision 1.9
diff -u -r1.9 java-interp.h
--- java-interp.h	2000/02/18 21:22:06	1.9
+++ java-interp.h	2000/03/02 20:13:10
@@ -20,7 +20,6 @@
 
 #include <java/lang/Class.h>
 #include <java/lang/ClassLoader.h>
-#include <gnu/gcj/runtime/MethodInvocation.h>
 
 extern "C" {
 #include <ffi.h>
@@ -135,7 +134,6 @@
 
   friend class _Jv_ClassReader;
   friend class _Jv_InterpMethodInvocation;
-  friend class gnu::gcj::runtime::MethodInvocation;
 
   friend void _Jv_PrepareClass(jclass);
 };
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Class.h,v
retrieving revision 1.15
diff -u -r1.15 Class.h
--- Class.h	2000/01/26 23:56:36	1.15
+++ Class.h	2000/03/02 20:13:18
@@ -157,9 +157,6 @@
 private:
   void checkMemberAccess (jint flags);
 
-  // Various functions to handle class initialization.
-  java::lang::Throwable *hackTrampoline (jint, java::lang::Throwable *);
-  void hackRunInitializers (void);
   void initializeClass (void);
 
   // Friend functions implemented in natClass.cc.
Index: java/lang/Class.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Class.java,v
retrieving revision 1.7
diff -u -r1.7 Class.java
--- Class.java	2000/01/19 18:39:25	1.7
+++ Class.java	2000/03/02 20:13:18
@@ -172,32 +172,6 @@
       sm.checkMemberAccess(this, flags);
   }
 
-  // FIXME: this method exists only because we cannot catch Java
-  // exceptions from C++ code.  This is a helper for initializeClass.
-  private Throwable hackTrampoline (int what, Throwable old_exception)
-    {
-      Throwable new_val = null;
-      try
-	{
-	  if (what == 0)
-	    initializeClass ();
-	  else if (what == 1)
-	    hackRunInitializers ();
-	  else if (what == 2)
-	    new_val = new ExceptionInInitializerError (old_exception);
-	}
-      catch (Throwable t)
-	{
-	  new_val = t;
-	}
-      return new_val;
-    }
-
-  // FIXME: this is a hack to let us run the class initializers.  We
-  // could do it inline in initializeClass() if we could catch Java
-  // exceptions from C++.
-  private native void hackRunInitializers ();
-
   // Initialize the class.
   private native void initializeClass ();
 
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/ClassLoader.java,v
retrieving revision 1.7
diff -u -r1.7 ClassLoader.java
--- ClassLoader.java	2000/01/19 18:39:25	1.7
+++ ClassLoader.java	2000/03/02 20:13:19
@@ -1,6 +1,6 @@
 // ClassLoader.java - Define policies for loading Java classes.
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -233,28 +233,6 @@
 				     int len)
     throws java.lang.ClassNotFoundException, java.lang.LinkageError;
 
-
-  /** This is called by defineClass0, once the "raw" and uninitialized
-   * class object has been created, and handles exceptions generated
-   * while actually defining the class (_Jv_DefineClass).  defineClass0
-   * holds the lock on the new class object, so it needs to capture
-   * these exceptions.  */
-
-  private static Throwable defineClass1 (Class klass, byte[] data,
-					 int offset, int length)
-  {
-    try {
-      defineClass2 (klass, data, offset, length);
-    } catch (Throwable x) {
-      return x;
-    }
-    return null;
-  }
- 
-  /** This is just a wrapper for _Jv_DefineClass */
-  private static native void defineClass2 (Class klass, byte[] data, 
-				    int offset, int length)
-    throws Throwable;
 
   /** 
    * Link the given class.  This will bring the class to a state where
Index: java/lang/Object.h
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Object.h,v
retrieving revision 1.3
diff -u -r1.3 Object.h
--- Object.h	2000/01/19 18:39:26	1.3
+++ Object.h	2000/03/02 20:13:19
@@ -1,6 +1,6 @@
 // Object.h - Header file for java.lang.Object.  -*- c++ -*-
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -69,8 +69,6 @@
 
   // Initialize the sync_info field.
   void sync_init (void);
-
-  static void hack12_6 (jobject f);
 };
 
 #endif /* __JAVA_LANG_OBJECT_H__ */
Index: java/lang/Object.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Object.java,v
retrieving revision 1.2
diff -u -r1.2 Object.java
--- Object.java	2000/01/19 18:39:26	1.2
+++ Object.java	2000/03/02 20:13:19
@@ -1,6 +1,6 @@
 // Object.java - The root of all evil.
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -65,21 +65,6 @@
   // This initializes the sync_info member.  It is here for
   // completeness (some day we'll be able to auto-generate Object.h).
   private final native void sync_init ();
-
-  // This exists as a workaround for the fact that we can't catch a
-  // Java Exception from C++.  This is from section 12.6 of the Java
-  // Language Spec.  FIXME: remove this once exception processing
-  // works.
-  private static final void hack12_6 (Object f)
-  {
-    try
-      {
-	f.finalize();
-      }
-    catch (Throwable x)
-      {
-      }
-  }
 
   // Note that we don't mention the sync_info field here.  If we do,
   // jc1 will not work correctly.
Index: java/lang/Thread.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/Thread.java,v
retrieving revision 1.6
diff -u -r1.6 Thread.java
--- Thread.java	2000/02/15 08:47:16	1.6
+++ Thread.java	2000/03/02 20:13:19
@@ -116,8 +116,8 @@
   public final native void resume ();
 
   // This method exists only to avoid a warning from the C++ compiler.
-  private static final native void run__ (Object obj);
-  private native final void finish_ ();
+  private static final native void run_ (Object obj);
+  private final native void finish_ ();
 
   // Convenience method to check and clear the thread's interrupted status.  
   private boolean isInterrupted_ ()
@@ -127,28 +127,6 @@
     return r;
   }
   
-  private final void run_ ()
-  {
-    try
-      {
-	run ();
-      }
-    catch (Throwable e)
-      {
-	// Uncaught exceptions are forwarded to the ThreadGroup.  If
-	// this results in an uncaught exception, that is ignored.
-	try
-	  {
-	    group.uncaughtException(this, e);
-	  }
-	catch (Throwable f)
-	  {
-	    // Nothing.
-	  }
-      }
-    finish_ ();
-  }
-
   public void run ()
   {
     if (runnable != null)
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natClass.cc,v
retrieving revision 1.16
diff -u -r1.16 natClass.cc
--- natClass.cc	2000/01/19 18:39:26	1.16
+++ natClass.cc	2000/03/02 20:13:19
@@ -27,6 +27,7 @@
 #include <java/lang/reflect/Constructor.h>
 #include <java/lang/AbstractMethodError.h>
 #include <java/lang/ClassNotFoundException.h>
+#include <java/lang/ExceptionInInitializerError.h>
 #include <java/lang/IllegalAccessException.h>
 #include <java/lang/IllegalAccessError.h>
 #include <java/lang/IncompatibleClassChangeError.h>
@@ -690,15 +691,6 @@
 #endif
 }
 
-// FIXME.
-void
-java::lang::Class::hackRunInitializers (void)
-{
-  _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name, void_signature);
-  if (meth)
-    ((void (*) (void)) meth->ncode) ();
-}
-
 // This implements the initialization process for a class.  From Spec
 // section 12.4.2.
 void
@@ -764,46 +756,53 @@
   // Step 7.
   if (! isInterface () && superclass)
     {
-      // FIXME: We can't currently catch a Java exception in C++ code.
-      // So instead we call a Java trampoline.  It returns an
-      // exception, or null.
-      jobject except = superclass->hackTrampoline(0, NULL);
-      if (except)
+      try
 	{
+	  superclass->initializeClass ();
+	}
+      catch (java::lang::Throwable *except)
+	{
 	  // Caught an exception.
 	  _Jv_MonitorEnter (this);
 	  state = JV_STATE_ERROR;
 	  notifyAll ();
 	  _Jv_MonitorExit (this);
-	  JvThrow (except);
+	  throw except;
 	}
     }
 
-  // Step 8.
-  // FIXME: once again we have to go through a trampoline.
-  java::lang::Throwable *except = hackTrampoline (1, NULL);
-
-  // Steps 9, 10, 11.
-  if (! except)
+  // Steps 8, 9, 10, 11.
+  try
     {
-      _Jv_MonitorEnter (this);
-      state = JV_STATE_DONE;
+      _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
+					     void_signature);
+      if (meth)
+	((void (*) (void)) meth->ncode) ();
     }
-  else
+  catch (java::lang::Throwable *except)
     {
       if (! ErrorClass.isInstance(except))
 	{
-	  // Once again we must use the trampoline.  In this case we
-	  // have to detect an OutOfMemoryError.
-	  except = hackTrampoline(2, except);
+	  try
+	    {
+	      except = new ExceptionInInitializerError (except);
+	    }
+	  catch (java::lang::Throwable *t)
+	    {
+	      except = t;
+	    }
 	}
       _Jv_MonitorEnter (this);
       state = JV_STATE_ERROR;
+      notifyAll ();
+      _Jv_MonitorExit (this);
+      JvThrow (except);
     }
+
+  _Jv_MonitorEnter (this);
+  state = JV_STATE_DONE;
   notifyAll ();
   _Jv_MonitorExit (this);
-  if (except)
-    JvThrow (except);
 }
 
 
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.17
diff -u -r1.17 natClassLoader.cc
--- natClassLoader.cc	2000/02/10 17:15:22	1.17
+++ natClassLoader.cc	2000/03/02 20:13:20
@@ -58,15 +58,6 @@
   return system;
 }
 
-void
-java::lang::ClassLoader::defineClass2 (jclass klass, jbyteArray data,
-				       jint offset, jint length)
-{
-#ifdef INTERPRETER
-  _Jv_DefineClass (klass, data, offset, length);
-#endif
-}
-
 java::lang::Class *
 java::lang::ClassLoader::defineClass0 (jstring name,
 				       jbyteArray data, 
@@ -94,11 +85,11 @@
       klass->name = name2;
     }
 
-  // this will do the magic.  loadInto also operates
-  // as an exception trampoline for now...
-  Throwable *ex = defineClass1 (klass, data, offset, length);
-    
-  if (ex)  // we failed to load it
+  try
+    {
+      _Jv_DefineClass (klass, data, offset, length);
+    }
+  catch (java::lang::Throwable *ex)
     {
       klass->state = JV_STATE_ERROR;
       klass->notifyAll ();
@@ -106,15 +97,15 @@
       _Jv_UnregisterClass (klass);
 
       _Jv_MonitorExit (klass);
-	  
+
       // FIXME: Here we may want to test that EX does
       // indeed represent a valid exception.  That is,
       // anything but ClassNotFoundException, 
       // or some kind of Error.
-	  
+
       JvThrow (ex);
     }
-    
+
   // if everything proceeded sucessfully, we're loaded.
   JvAssert (klass->state == JV_STATE_LOADED);
 
Index: java/lang/natObject.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natObject.cc,v
retrieving revision 1.6
diff -u -r1.6 natObject.cc
--- natObject.cc	2000/01/19 18:39:26	1.6
+++ natObject.cc	2000/03/02 20:13:20
@@ -1,6 +1,6 @@
 // natObject.cc - Implementation of the Object class.
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -242,5 +242,13 @@
 void
 _Jv_FinalizeObject (jobject obj)
 {
-  java::lang::Object::hack12_6(obj);
+  // Ignore exceptions.  From section 12.6 of the Java Language Spec.
+  try
+    {
+      obj->finalize ();
+    }
+  catch (java::lang::Throwable *t)
+    {
+      // Ignore.
+    }
 }
Index: java/lang/natThread.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natThread.cc,v
retrieving revision 1.13
diff -u -r1.13 natThread.cc
--- natThread.cc	2000/02/15 08:47:16	1.13
+++ natThread.cc	2000/03/02 20:13:21
@@ -263,9 +263,9 @@
 }
 
 void
-java::lang::Thread::finish_ (void)
+java::lang::Thread::finish_ ()
 {
-  // Notify all threads waiting to join this thread.
+  // Notify all threads waiting to join this this.
   _Jv_MonitorEnter (this);
   alive_flag = false;
 
@@ -285,10 +285,28 @@
 }
 
 void
-java::lang::Thread::run__ (jobject obj)
+java::lang::Thread::run_ (jobject obj)
 {
   java::lang::Thread *thread = (java::lang::Thread *) obj;
-  thread->run_ ();
+  try
+    {
+      thread->run ();
+    }
+  catch (java::lang::Throwable *t)
+    {
+      // Uncaught exceptions are forwarded to the ThreadGroup.  If
+      // this results in an uncaught exception, that is ignored.
+      try
+	{
+	  thread->group->uncaughtException (thread, t);
+	}
+      catch (java::lang::Throwable *f)
+	{
+	  // Nothing.
+	}
+    }
+
+  thread->finish_ ();
 }
 
 void
@@ -301,7 +319,7 @@
 
   alive_flag = true;
   natThread *nt = (natThread *) data;
-  _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &run__);
+  _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &run_);
 }
 
 void
Index: java/lang/reflect/Method.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/reflect/Method.java,v
retrieving revision 1.5
diff -u -r1.5 Method.java
--- Method.java	2000/01/19 18:39:26	1.5
+++ Method.java	2000/03/02 20:13:21
@@ -1,6 +1,6 @@
 // Method.java - Represent method of class or interface.
 
-/* Copyright (C) 1998, 1999  Red Hat, Inc.
+/* Copyright (C) 1998, 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -67,30 +67,6 @@
       // FIXME.
       return name.hashCode() + declaringClass.getName().hashCode();
     }
-
-  // This is used to perform an actual method call via ffi.
-  private static final native void hack_call (RawData cif,
-					      RawData method,
-					      RawData ret_value,
-					      RawData values);
-
-  // Perform an ffi call while capturing exceptions.  We have to do
-  // this because we can't catch Java exceptions from C++.
-  static final Throwable hack_trampoline (RawData cif,
-					  RawData method,
-					  RawData ret_value,
-					  RawData values)
-  {
-    try
-      {
-	hack_call (cif, method, ret_value, values);
-      }
-    catch (Throwable x)
-      {
-	return x;
-      }
-    return null;
-  }
 
   public native Object invoke (Object obj, Object[] args)
     throws IllegalAccessException, IllegalArgumentException,
Index: java/lang/reflect/natMethod.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/reflect/natMethod.cc,v
retrieving revision 1.8
diff -u -r1.8 natMethod.cc
--- natMethod.cc	2000/01/21 23:50:31	1.8
+++ natMethod.cc	2000/03/02 20:13:23
@@ -152,21 +152,6 @@
   return r;
 }
 
-// Actually perform an FFI call.
-void
-java::lang::reflect::Method::hack_call (gnu::gcj::RawData *rcif,
-					gnu::gcj::RawData *rmethod,
-					gnu::gcj::RawData *rret_value,
-					gnu::gcj::RawData *rvalues)
-{
-  ffi_cif *cif = (ffi_cif *) rcif;
-  void (*method) (...) = (void (*) (...)) rmethod;
-  void *ret_value = (void *) rret_value;
-  void **values = (void **) rvalues;
-
-  ffi_call (cif, method, ret_value, values);
-}
-
 jobject
 java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
 {
@@ -419,19 +404,23 @@
 
   // FIXME: initialize class here.
 
-  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 *) 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);
+
+  Throwable *ex = NULL;
+
+  try
+    {
+      ffi_call (&cif, (void (*) (...)) meth->ncode, result, values);
+    }
+  catch (Throwable *ex2)
+    {
+      // 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 (ex2);
+    }
 
   if (is_constructor)
     result->l = obj;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]