* testsuite/libjava.jni/pr29812.java: New file.
* testsuite/libjava.jni/pr29812_injar.java: New file.
* testsuite/libjava.jni/pr29812_injar.jar: New file.
* testsuite/libjava.jni/pr29812.out: New file.
* testsuite/libjava.jni/pr29812_injar.c: New file.
* testsuite/libjava.jni/pr29812_injar.h: New file.
* testsuite/libjava.jni/pr29812.jar: New file.
* testsuite/libjava.jni/pr29812.c: New file.
* testsuite/libjava.jni/pr29812.h: New file.
* testsuite/libjava.jni/jni.exp (gcj_jni_get_cxxflags_invocation):
New proc.
(gcj_jni_invocation_test_one): Use it.
(gcj_jni_pr29812): New proc.
(gcj_jni_run): Use it.
* java/lang/natRuntime.cc (_load): Push a new system frame before
calling JNI_OnLoad.
* include/jvm.h (_Jv_JNI_PopSystemFrame): Declare.
(_Jv_GetJNIEnvNewFrameWithLoader): Likewise.
* jni.cc (struct _Jv_JNI_LocalFrame) <marker>: Now unsigned char.
<allocated_p>: Now bool.
<loader>: New field.
(_Jv_JNI_EnsureLocalCapacity): Updated.
(_Jv_JNI_NewLocalRef): Likewise.
(_Jv_JNI_NewLocalRef): Likewise.
(_Jv_JNI_PopLocalFrame): Likewise.
(_Jv_JNI_FindClass): Likewise.
(_Jv_GetJNIEnvNewFrame): Likewise.
(_Jv_JNI_AttachCurrentThread): Likewise.
(_Jv_GetJNIEnvNewFrameWithLoader): New function.
(_Jv_GetJNIEnvNewFrame): Use it.
* include/jni_md.h (_CLASSPATH_JNIENV_CONTENTS): Removed 'klass'.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121064
138bc75d-0d04-0410-961f-
82ee72b054a4
2007-01-22 Tom Tromey <tromey@redhat.com>
+ PR java/29812:
+ * testsuite/libjava.jni/pr29812.java: New file.
+ * testsuite/libjava.jni/pr29812_injar.java: New file.
+ * testsuite/libjava.jni/pr29812_injar.jar: New file.
+ * testsuite/libjava.jni/pr29812.out: New file.
+ * testsuite/libjava.jni/pr29812_injar.c: New file.
+ * testsuite/libjava.jni/pr29812_injar.h: New file.
+ * testsuite/libjava.jni/pr29812.jar: New file.
+ * testsuite/libjava.jni/pr29812.c: New file.
+ * testsuite/libjava.jni/pr29812.h: New file.
+ * testsuite/libjava.jni/jni.exp (gcj_jni_get_cxxflags_invocation):
+ New proc.
+ (gcj_jni_invocation_test_one): Use it.
+ (gcj_jni_pr29812): New proc.
+ (gcj_jni_run): Use it.
+ * java/lang/natRuntime.cc (_load): Push a new system frame before
+ calling JNI_OnLoad.
+ * include/jvm.h (_Jv_JNI_PopSystemFrame): Declare.
+ (_Jv_GetJNIEnvNewFrameWithLoader): Likewise.
+ * jni.cc (struct _Jv_JNI_LocalFrame) <marker>: Now unsigned char.
+ <allocated_p>: Now bool.
+ <loader>: New field.
+ (_Jv_JNI_EnsureLocalCapacity): Updated.
+ (_Jv_JNI_NewLocalRef): Likewise.
+ (_Jv_JNI_NewLocalRef): Likewise.
+ (_Jv_JNI_PopLocalFrame): Likewise.
+ (_Jv_JNI_FindClass): Likewise.
+ (_Jv_GetJNIEnvNewFrame): Likewise.
+ (_Jv_JNI_AttachCurrentThread): Likewise.
+ (_Jv_GetJNIEnvNewFrameWithLoader): New function.
+ (_Jv_GetJNIEnvNewFrame): Use it.
+ * include/jni_md.h (_CLASSPATH_JNIENV_CONTENTS): Removed 'klass'.
+
+2007-01-22 Tom Tromey <tromey@redhat.com>
+
* libtool-version: Bump current to 9.
2007-01-22 Andrew Haley <aph@redhat.com>
/* jni_md.h
- Copyright (C) 2001, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2005, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
/* The current exception. */ \
jthrowable ex; \
\
- /* The class of the current native method. */ \
- jclass klass; \
- \
/* The chain of local frames. */ \
struct _Jv_JNI_LocalFrame *locals; \
\
/* Free a JNIEnv. */
void _Jv_FreeJNIEnv (_Jv_JNIEnv *);
-/* Free a JNIEnv. */
-void _Jv_FreeJNIEnv (_Jv_JNIEnv *);
+extern "C" void _Jv_JNI_PopSystemFrame (_Jv_JNIEnv *);
+_Jv_JNIEnv *_Jv_GetJNIEnvNewFrameWithLoader (::java::lang::ClassLoader *);
struct _Jv_JavaVM;
_Jv_JavaVM *_Jv_GetJavaVM ();
// FIXME: what?
return;
}
+
+ // Push a new frame so that JNI_OnLoad will get the right class
+ // loader if it calls FindClass.
+ ::java::lang::ClassLoader *loader
+ = _Jv_StackTrace::GetFirstNonSystemClassLoader();
+ JNIEnv *env = _Jv_GetJNIEnvNewFrameWithLoader (loader);
jint vers = ((jint (JNICALL *) (JavaVM *, void *)) onload) (vm, NULL);
+ _Jv_JNI_PopSystemFrame (env);
if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2
&& vers != JNI_VERSION_1_4)
{
// This structure is used to keep track of local references.
struct _Jv_JNI_LocalFrame
{
- // This is true if this frame object represents a pushed frame (eg
- // from PushLocalFrame).
- int marker;
+ // This is one of the MARK_ constants.
+ unsigned char marker;
// Flag to indicate some locals were allocated.
- int allocated_p;
+ bool allocated_p;
// Number of elements in frame.
int size;
+ // The class loader of the JNI method that allocated this frame.
+ ::java::lang::ClassLoader *loader;
+
// Next frame in chain.
_Jv_JNI_LocalFrame *next;
frame->marker = MARK_NONE;
frame->size = size;
- frame->allocated_p = 0;
+ frame->allocated_p = false;
memset (&frame->vec[0], 0, size * sizeof (jobject));
+ frame->loader = env->locals->loader;
frame->next = env->locals;
env->locals = frame;
set = true;
done = true;
frame->vec[i] = obj;
- frame->allocated_p = 1;
+ frame->allocated_p = true;
break;
}
}
_Jv_JNI_EnsureLocalCapacity (env, 16);
// We know the first element of the new frame will be ok.
env->locals->vec[0] = obj;
- env->locals->allocated_p = 1;
+ env->locals->allocated_p = true;
}
mark_for_gc (obj, local_ref_table);
{
if (rf->allocated_p)
memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
- rf->allocated_p = 0;
+ rf->allocated_p = false;
rf = NULL;
break;
}
jstring n = JvNewStringUTF (s);
java::lang::ClassLoader *loader = NULL;
- if (env->klass != NULL)
- loader = env->klass->getClassLoaderInternal ();
+ if (env->locals->loader != NULL)
+ loader = env->locals->loader;
if (loader == NULL)
{
buf[here] = '\0';
}
-// Return the current thread's JNIEnv; if one does not exist, create
-// it. Also create a new system frame for use. This is `extern "C"'
-// because the compiler calls it.
-extern "C" JNIEnv *
-_Jv_GetJNIEnvNewFrame (jclass klass)
+JNIEnv *
+_Jv_GetJNIEnvNewFrameWithLoader (::java::lang::ClassLoader *loader)
{
JNIEnv *env = _Jv_GetCurrentJNIEnv ();
if (__builtin_expect (env == NULL, false))
{
env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
env->p = &_Jv_JNIFunctions;
- env->klass = klass;
env->locals = NULL;
// We set env->ex below.
_Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
+ (FRAME_SIZE
* sizeof (jobject)));
-
+
env->bottom_locals->marker = MARK_SYSTEM;
env->bottom_locals->size = FRAME_SIZE;
env->bottom_locals->next = NULL;
- env->bottom_locals->allocated_p = 0;
+ env->bottom_locals->allocated_p = false;
+ // We set the klass field below.
memset (&env->bottom_locals->vec[0], 0,
env->bottom_locals->size * sizeof (jobject));
// built, above.
if (__builtin_expect (env->locals == NULL, true))
- env->locals = env->bottom_locals;
-
+ {
+ env->locals = env->bottom_locals;
+ env->locals->loader = loader;
+ }
else
{
// Alternatively, we might be re-entering JNI, in which case we can't
// reuse the bottom_locals frame, because it is already underneath
// us. So we need to make a new one.
-
_Jv_JNI_LocalFrame *frame
= (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
+ (FRAME_SIZE
* sizeof (jobject)));
-
+
frame->marker = MARK_SYSTEM;
frame->size = FRAME_SIZE;
- frame->allocated_p = 0;
+ frame->allocated_p = false;
frame->next = env->locals;
+ frame->loader = loader;
memset (&frame->vec[0], 0,
frame->size * sizeof (jobject));
return env;
}
+// Return the current thread's JNIEnv; if one does not exist, create
+// it. Also create a new system frame for use. This is `extern "C"'
+// because the compiler calls it.
+extern "C" JNIEnv *
+_Jv_GetJNIEnvNewFrame (jclass klass)
+{
+ return _Jv_GetJNIEnvNewFrameWithLoader (klass->getClassLoaderInternal());
+}
+
// Destroy the env's reusable resources. This is called from the thread
// destructor "finalize_native" in natThread.cc
void
return JNI_ERR;
env->p = &_Jv_JNIFunctions;
env->ex = NULL;
- env->klass = NULL;
env->bottom_locals
= (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
+ (FRAME_SIZE
return JNI_ERR;
}
- env->locals->allocated_p = 0;
+ env->locals->allocated_p = false;
env->locals->marker = MARK_SYSTEM;
env->locals->size = FRAME_SIZE;
+ env->locals->loader = NULL;
env->locals->next = NULL;
for (int i = 0; i < env->locals->size; ++i)
# The base name. We use it for several purposes.
set main [file rootname [file tail $file]]
- if {! [runtest_file_p $runtests $main]} {
+ if {! [runtest_file_p $runtests $main]
+ || $main == "pr29812" || $main == "pr29812_injar"} {
# Simply skip it.
return 1
}
return 1
}
+proc gcj_jni_get_cxxflags_invocation {} {
+ # Darwin needs -liconv linked, otherwise we get some unresolved.
+ # If you're building the compiler with --prefix set to a place
+ # where it's not yet installed, then the linker won't be able to
+ # find the libgcc used by libffi.dylib. We could pass the
+ # -dylib_file option, but that's complicated, and it's much easier
+ # to just make the linker find libgcc using -L options.
+ # Similar logic applies to libgcj.
+ if { [istarget "*-*-darwin*"] } {
+ set cxxflags "-L../.libs -shared-libgcc -ljvm -lgcj -liconv"
+ } else {
+ global LIBJAVA
+ if [info exists LIBJAVA] {
+ set libjava $LIBJAVA;
+ } else {
+ set libjava [libjava_find_lib libjava gcj]
+ }
+ set cxxflags "$libjava -ljvm"
+ }
+
+ if { [istarget "*-*-solaris*"] } {
+ lappend cxxflags "-lsocket"
+ }
+
+ return $cxxflags
+}
+
# Do all the work for a single invocation API test. Return 0 on
# failure.
proc gcj_jni_invocation_test_one {file} {
# pass "bytecompile $file"
set cfile [file rootname $file].c
- # Darwin needs -liconv linked, otherwise we get some unresolved.
- # If you're building the compiler with --prefix set to a place
- # where it's not yet installed, then the linker won't be able to
- # find the libgcc used by libffi.dylib. We could pass the
- # -dylib_file option, but that's complicated, and it's much easier
- # to just make the linker find libgcc using -L options.
- # Similar logic applies to libgcj.
- if { [istarget "*-*-darwin*"] } {
- set cxxflags "-L../.libs -shared-libgcc -ljvm -lgcj -liconv"
- } else {
- global LIBJAVA
- if [info exists LIBJAVA] {
- set libjava $LIBJAVA;
- } else {
- set libjava [libjava_find_lib libjava gcj]
- }
- set cxxflags "$libjava -ljvm"
- }
-
- if { [istarget "*-*-solaris*"] } {
- lappend cxxflags "-lsocket"
- }
+ set cxxflags [gcj_jni_get_cxxflags_invocation]
if {! [gcj_jni_invocation_compile_c_to_binary $cfile $cxxflags]} {
# FIXME
return 0
return 1
}
+proc gcj_jni_pr29812 {} {
+ global srcdir subdir
+ global INTERPRETER runtests
+
+ # Set up a global we need.
+ libjava_arguments
+
+ set b ${srcdir}/${subdir}
+
+ if {! [runtest_file_p $runtests pr29812]} {
+ # Simply skip it.
+ return 1
+ }
+
+ if {! [gcj_jni_compile_c_to_so $b/pr29812.c ""]} {
+ return 0
+ }
+ if {! [gcj_jni_compile_c_to_so $b/pr29812_injar.c ""]} {
+ return 0
+ }
+
+ set gij [libjava_find_gij]
+ if {$INTERPRETER == "yes" && $gij != ""} {
+ if {! [libjava_invoke pr29812 "gij test" opts $gij \
+ "" $b/pr29812.out "" \
+ -classpath $b/pr29812.jar pr29812 $b/pr29812_injar.jar]} {
+ return 0
+ }
+ }
+
+ # When we succeed we remove all our clutter.
+ eval gcj_cleanup [glob -nocomplain -- *pr29812*]
+}
+
# Run the JNI tests.
proc gcj_jni_run {} {
global srcdir subdir
foreach x $srcfiles {
gcj_jni_invocation_test_one $x
}
+
+ gcj_jni_pr29812
} else {
verbose "JNI tests not run in cross-compilation environment"
}
--- /dev/null
+#include <pr29812.h>
+
+void
+Java_pr29812_baseN (JNIEnv *env, jclass barf)
+{
+ /* nothing */
+}
--- /dev/null
+/* DO NOT EDIT THIS FILE - it is machine generated */
+
+#include <jni.h>
+
+#ifndef __pr29812__
+#define __pr29812__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+JNIEXPORT void JNICALL Java_pr29812_baseN (JNIEnv *env, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __pr29812__ */
--- /dev/null
+import java.io.File;
+import java.net.*;
+import java.lang.reflect.Method;
+
+public class pr29812
+{
+ static {
+ System.loadLibrary("pr29812");
+ }
+
+ public static native void baseN();
+
+ public static void main(String[] args) throws Throwable
+ {
+ // Make sure JNI environment is initialized.
+ baseN();
+
+ File jar = new File(args[0]);
+ URL u = jar.toURL();
+ URLClassLoader uc = new URLClassLoader(new URL[] { u });
+ Class k = uc.loadClass("pr29812_injar");
+ Method m = k.getMethod("doit", (Class[]) null);
+ m.invoke(null, (Object[]) null);
+ }
+}
--- /dev/null
+
+#include <stdlib.h>
+#include <assert.h>
+#include <pr29812_injar.h>
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad (JavaVM *vm, void *nothing)
+{
+ JNIEnv *env;
+ jint r;
+ jclass k;
+
+ r = (*vm)->GetEnv (vm, (void **) &env, JNI_VERSION_1_2);
+ assert (r == JNI_OK);
+ k = (*env)->FindClass (env, "pr29812_injar$inner");
+ assert (k != NULL);
+
+ return JNI_VERSION_1_2;
+}
+
+void
+Java_pr29812_1injar_doit (JNIEnv *env, jclass b)
+{
+ jclass k = (*env)->FindClass(env, "pr29812_injar$inner");
+ assert (k != NULL);
+}
--- /dev/null
+/* DO NOT EDIT THIS FILE - it is machine generated */
+
+#include <jni.h>
+
+#ifndef __pr29812_1injar__
+#define __pr29812_1injar__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+JNIEXPORT void JNICALL Java_pr29812_1injar_doit (JNIEnv *env, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __pr29812_1injar__ */
--- /dev/null
+public class pr29812_injar
+{
+ public class inner
+ {
+ }
+
+ static {
+ System.loadLibrary("pr29812_injar");
+ }
+
+ public static native void doit();
+}