This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Patch: FYI: PR 11951
- From: Tom Tromey <tromey at redhat dot com>
- To: GCC libjava patches <java-patches at gcc dot gnu dot org>
- Date: 18 Aug 2003 08:26:54 -0600
- Subject: Patch: FYI: PR 11951
- Reply-to: tromey at redhat dot com
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