This is the mail archive of the java-patches@gcc.gnu.org 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]
Other format: [Raw text]

Patch: FYI: PR 11951


I'm checking this in on the trunk.

This fixes PR 11951 plus a couple other JNI things.

I've changed the interface to _Jv_CallAnyMethodA; this lets us
correctly decide whether or not to wrap exceptions thrown by the
called method, and made it throw any exception rather than just return
it.  I've added a bit more error checking to _Jv_CallAnyMethodA.  And,
I've changed it to initialize the return value (depending on type) to
further insulate us from buggy code.

There's a new test case appended.  Tested on x86 Red Hat Linux 9.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	PR libgcj/11951:
	* java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA): Returns
	void.  Throw VirtualMachineError if ffi fails.  Initialize return
	value.  Added is_jni_call argument; only wrap exception if not a
	JNI call.  Use descriptive message if operation not supported.
	(_Jv_GetTypesFromSignature): Use declaring class' loader to find
	array class.
	* include/jvm.h (_Jv_CallAnyMethodA): Updated declaration.
	* jni.cc (_Jv_JNI_CallAnyMethodV): Updated for new form of
	_Jv_CallAnyMethodA.
	(_Jv_JNI_CallAnyMethodA): Likewise.
	(_Jv_JNI_CallAnyVoidMethodV): Likewise.
	(_Jv_JNI_CallAnyVoidMethodA): Likewise.

Index: jni.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni.cc,v
retrieving revision 1.73
diff -u -r1.73 jni.cc
--- jni.cc 21 Jul 2003 01:54:05 -0000 1.73
+++ jni.cc 18 Aug 2003 14:31:16 -0000
@@ -777,12 +777,9 @@
 	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;
+      _Jv_CallAnyMethodA (obj, return_type, id,
+			  style == constructor,
+			  arg_types, args, &result);
 
       // We cheat a little here.  FIXME.
       return wrap_value (env, * (T *) &result);
@@ -847,12 +844,9 @@
 	}
 
       jvalue result;
-      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
-					  style == constructor,
-					  arg_types, arg_copy, &result);
-
-      if (ex != NULL)
-	env->ex = ex;
+      _Jv_CallAnyMethodA (obj, return_type, id,
+			  style == constructor,
+			  arg_types, arg_copy, &result);
 
       // We cheat a little here.  FIXME.
       return wrap_value (env, * (T *) &result);
@@ -893,12 +887,9 @@
       if (style == constructor)
 	return_type = klass;
 
-      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
-					  style == constructor,
-					  arg_types, args, NULL);
-
-      if (ex != NULL)
-	env->ex = ex;
+      _Jv_CallAnyMethodA (obj, return_type, id,
+			  style == constructor,
+			  arg_types, args, NULL);
     }
   catch (jthrowable t)
     {
@@ -947,12 +938,9 @@
 	    arg_copy[i].l = unwrap (args[i].l);
 	}
 
-      jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
-					  style == constructor,
-					  arg_types, args, NULL);
-
-      if (ex != NULL)
-	env->ex = ex;
+      _Jv_CallAnyMethodA (obj, return_type, id,
+			  style == constructor,
+			  arg_types, args, NULL);
     }
   catch (jthrowable t)
     {
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.56
diff -u -r1.56 jvm.h
--- include/jvm.h 21 Jul 2003 01:54:05 -0000 1.56
+++ include/jvm.h 18 Aug 2003 14:31:16 -0000
@@ -335,13 +335,14 @@
 				   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 void _Jv_CallAnyMethodA (jobject obj,
+				jclass return_type,
+				jmethodID meth,
+				jboolean is_constructor,
+				JArray<jclass> *parameter_types,
+				jvalue *args,
+				jvalue *result,
+				jboolean is_jni_call = true);
 
 extern jobject _Jv_NewMultiArray (jclass, jint ndims, jint* dims)
   __attribute__((__malloc__));
Index: java/lang/reflect/natMethod.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/reflect/natMethod.cc,v
retrieving revision 1.32
diff -u -r1.32 natMethod.cc
--- java/lang/reflect/natMethod.cc 21 Jul 2003 01:54:06 -0000 1.32
+++ java/lang/reflect/natMethod.cc 18 Aug 2003 14:31:16 -0000
@@ -31,6 +31,7 @@
 #include <java/lang/IllegalArgumentException.h>
 #include <java/lang/NullPointerException.h>
 #include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/VirtualMachineError.h>
 #include <java/lang/Class.h>
 #include <gcj/method.h>
 #include <gnu/gcj/RawData.h>
@@ -309,9 +310,8 @@
 	  break;
 	}
 
-      // FIXME: 2'nd argument should be "current loader"
       while (--num_arrays >= 0)
-	type = _Jv_GetArrayClass (type, 0);
+	type = _Jv_GetArrayClass (type, loader);
       // ARGPTR can be NULL if we are processing the return value of a
       // call from Constructor.
       if (argPtr)
@@ -328,14 +328,15 @@
 // 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
+void
 _Jv_CallAnyMethodA (jobject obj,
 		    jclass return_type,
 		    jmethodID meth,
 		    jboolean is_constructor,
 		    JArray<jclass> *parameter_types,
 		    jvalue *args,
-		    jvalue *result)
+		    jvalue *result,
+		    jboolean is_jni_call)
 {
 #ifdef USE_LIBFFI
   JvAssert (! is_constructor || ! obj);
@@ -409,15 +410,11 @@
 
   if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, param_count,
 		    rtype, argtypes) != FFI_OK)
-    {
-      // FIXME: throw some kind of VirtualMachineError here.
-    }
+    throw new java::lang::VirtualMachineError(JvNewStringLatin1("internal error: ffi_prep_cif failed"));
 
   using namespace java::lang;
   using namespace java::lang::reflect;
 
-  Throwable *ex = NULL;
-
   union
   {
     ffi_arg i;
@@ -427,17 +424,51 @@
     jdouble d;
   } ffi_result;
 
+  switch (rtype->type)
+    {
+    case FFI_TYPE_VOID:
+      break;
+    case FFI_TYPE_SINT8:
+      result->b = 0;
+      break;
+    case FFI_TYPE_SINT16:
+      result->s = 0;
+      break;
+    case FFI_TYPE_UINT16:
+      result->c = 0;
+      break;
+    case FFI_TYPE_SINT32:
+      result->i = 0;
+      break;
+    case FFI_TYPE_SINT64:
+      result->j = 0;
+      break;
+    case FFI_TYPE_FLOAT:
+      result->f = 0;
+      break;
+    case FFI_TYPE_DOUBLE:
+      result->d = 0;
+      break;
+    case FFI_TYPE_POINTER:
+      result->l = 0;
+      break;
+    default:
+      JvFail ("Unknown ffi_call return type");
+      break;
+    }
+
   try
     {
       ffi_call (&cif, (void (*)()) meth->ncode, &ffi_result, values);
     }
-  catch (Throwable *ex2)
+  catch (Throwable *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 (ex2);
+      // For JNI we just throw the real error.  For reflection, we
+      // wrap the underlying method's exception in an
+      // InvocationTargetException.
+      if (! is_jni_call)
+	ex = new InvocationTargetException (ex);
+      throw ex;
     }
 
   // Since ffi_call returns integer values promoted to a word, use
@@ -481,11 +512,8 @@
 	  break;
 	}
     }
-
-  return ex;
 #else
-  throw new java::lang::UnsupportedOperationException;
-  return 0;
+  throw new java::lang::UnsupportedOperationException(JvNewStringLatin1("reflection not available in this build"));
 #endif // USE_LIBFFI
 }
 
@@ -562,16 +590,9 @@
     }
 
   jvalue ret_value;
-  java::lang::Throwable *ex = _Jv_CallAnyMethodA (obj,
-						  return_type,
-						  meth,
-						  is_constructor,
-						  parameter_types,
-						  argvals,
-						  &ret_value);
-
-  if (ex)
-    throw ex;
+  _Jv_CallAnyMethodA (obj, return_type, meth, is_constructor,
+		      parameter_types, argvals, &ret_value,
+		      false);
 
   jobject r;
 #define VAL(Wrapper, Field)  (new Wrapper (ret_value.Field))
Index: testsuite/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	PR libgcj/11951:
	* libjava.jni/pr11951.c: New file.
	* libjava.jni/pr11951.out: New file.
	* libjava.jni/pr11951.java: New file.

Index: testsuite/libjava.jni/pr11951.c
===================================================================
RCS file: testsuite/libjava.jni/pr11951.c
diff -N testsuite/libjava.jni/pr11951.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libjava.jni/pr11951.c 18 Aug 2003 14:31:17 -0000
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <pr11951.h>
+
+JNIEXPORT void JNICALL
+Java_pr11951_nmethod (JNIEnv *env, jclass myclass)
+{
+  jmethodID method;
+  jobject r;
+
+  method = (*env)->GetStaticMethodID (env, myclass, "dosomething",
+				      "()Ljava/lang/Object;");
+  r = (*env)->CallStaticObjectMethod (env, myclass, method);
+  printf ("%d\n", r == NULL);
+
+  (*env)->ExceptionClear (env);
+}
Index: testsuite/libjava.jni/pr11951.java
===================================================================
RCS file: testsuite/libjava.jni/pr11951.java
diff -N testsuite/libjava.jni/pr11951.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libjava.jni/pr11951.java 18 Aug 2003 14:31:17 -0000
@@ -0,0 +1,14 @@
+public class pr11951
+{
+  public static Object dosomething()
+  {
+    throw new Error();
+  }
+
+  public static native void nmethod();
+
+  public static void main(String[] args)
+  {
+    nmethod();
+  }
+}
Index: testsuite/libjava.jni/pr11951.out
===================================================================
RCS file: testsuite/libjava.jni/pr11951.out
diff -N testsuite/libjava.jni/pr11951.out
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/libjava.jni/pr11951.out 18 Aug 2003 14:31:17 -0000
@@ -0,0 +1 @@
+1


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