OSDN Git Service

PR java/29812:
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Jan 2007 23:04:16 +0000 (23:04 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Jan 2007 23:04:16 +0000 (23:04 +0000)
* 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

15 files changed:
libjava/ChangeLog
libjava/include/jni_md.h
libjava/include/jvm.h
libjava/java/lang/natRuntime.cc
libjava/jni.cc
libjava/testsuite/libjava.jni/jni.exp
libjava/testsuite/libjava.jni/pr29812.c [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812.h [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812.jar [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812.java [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812.out [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812_injar.c [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812_injar.h [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812_injar.jar [new file with mode: 0644]
libjava/testsuite/libjava.jni/pr29812_injar.java [new file with mode: 0644]

index 8d90a4c..e31a214 100644 (file)
@@ -1,5 +1,40 @@
 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>
index c550338..6ea90ab 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -58,9 +58,6 @@ typedef struct _Jv_JavaVM JavaVM;
   /* The current exception.  */                                                \
   jthrowable ex;                                                       \
                                                                        \
-  /* The class of the current native method.  */                       \
-  jclass klass;                                                                \
-                                                                       \
   /* The chain of local frames.  */                                    \
   struct _Jv_JNI_LocalFrame *locals;                                   \
                                                                        \
index 2da13bc..9a99a95 100644 (file)
@@ -592,8 +592,8 @@ void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *);
 /* 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 (); 
index ecaf7d3..64c8fbb 100644 (file)
@@ -207,7 +207,14 @@ java::lang::Runtime::_load (jstring path, jboolean do_search)
          // 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)
        {
index 9dc9780..59c1e5f 100644 (file)
@@ -85,16 +85,18 @@ extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions;
 // 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;
 
@@ -311,8 +313,9 @@ _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
 
   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;
 
@@ -350,7 +353,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
              set = true;
              done = true;
              frame->vec[i] = obj;
-             frame->allocated_p = 1;
+             frame->allocated_p = true;
              break;
            }
        }
@@ -368,7 +371,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
       _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);
@@ -397,7 +400,7 @@ _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop)
        {
          if (rf->allocated_p)
            memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
-         rf->allocated_p = 0;
+         rf->allocated_p = false;
          rf = NULL;
          break;
        }
@@ -541,8 +544,8 @@ _Jv_JNI_FindClass (JNIEnv *env, const char *name)
       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)
        {
@@ -2087,18 +2090,14 @@ mangled_name (jclass klass, _Jv_Utf8Const *func_name,
   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.
 
@@ -2107,11 +2106,12 @@ _Jv_GetJNIEnvNewFrame (jclass klass)
        _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));
 
@@ -2123,23 +2123,25 @@ _Jv_GetJNIEnvNewFrame (jclass klass)
   // 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));
@@ -2152,6 +2154,15 @@ _Jv_GetJNIEnvNewFrame (jclass klass)
   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 
@@ -2392,7 +2403,6 @@ _Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv,
     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
@@ -2404,9 +2414,10 @@ _Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv,
       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)
index 5fa6ede..1fff2b2 100644 (file)
@@ -101,7 +101,8 @@ proc gcj_jni_test_one {file} {
 
   # 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
   }
@@ -235,6 +236,33 @@ proc gcj_jni_invocation_compile_c_to_binary {file {options {}}} {
   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} {
@@ -259,29 +287,8 @@ 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
@@ -309,6 +316,40 @@ proc gcj_jni_invocation_test_one {file} {
   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
@@ -328,6 +369,8 @@ proc gcj_jni_run {} {
     foreach x $srcfiles {
       gcj_jni_invocation_test_one $x
     }
+
+    gcj_jni_pr29812
   } else {
     verbose "JNI tests not run in cross-compilation environment"
   }
diff --git a/libjava/testsuite/libjava.jni/pr29812.c b/libjava/testsuite/libjava.jni/pr29812.c
new file mode 100644 (file)
index 0000000..809d5ed
--- /dev/null
@@ -0,0 +1,7 @@
+#include <pr29812.h>
+
+void
+Java_pr29812_baseN (JNIEnv *env, jclass barf)
+{
+  /* nothing */
+}
diff --git a/libjava/testsuite/libjava.jni/pr29812.h b/libjava/testsuite/libjava.jni/pr29812.h
new file mode 100644 (file)
index 0000000..70d1999
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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__ */
diff --git a/libjava/testsuite/libjava.jni/pr29812.jar b/libjava/testsuite/libjava.jni/pr29812.jar
new file mode 100644 (file)
index 0000000..c3cf6ab
Binary files /dev/null and b/libjava/testsuite/libjava.jni/pr29812.jar differ
diff --git a/libjava/testsuite/libjava.jni/pr29812.java b/libjava/testsuite/libjava.jni/pr29812.java
new file mode 100644 (file)
index 0000000..4dde744
--- /dev/null
@@ -0,0 +1,25 @@
+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);
+  }
+}
diff --git a/libjava/testsuite/libjava.jni/pr29812.out b/libjava/testsuite/libjava.jni/pr29812.out
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libjava/testsuite/libjava.jni/pr29812_injar.c b/libjava/testsuite/libjava.jni/pr29812_injar.c
new file mode 100644 (file)
index 0000000..5b045ce
--- /dev/null
@@ -0,0 +1,26 @@
+
+#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);
+}
diff --git a/libjava/testsuite/libjava.jni/pr29812_injar.h b/libjava/testsuite/libjava.jni/pr29812_injar.h
new file mode 100644 (file)
index 0000000..40f74ff
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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__ */
diff --git a/libjava/testsuite/libjava.jni/pr29812_injar.jar b/libjava/testsuite/libjava.jni/pr29812_injar.jar
new file mode 100644 (file)
index 0000000..438dc00
Binary files /dev/null and b/libjava/testsuite/libjava.jni/pr29812_injar.jar differ
diff --git a/libjava/testsuite/libjava.jni/pr29812_injar.java b/libjava/testsuite/libjava.jni/pr29812_injar.java
new file mode 100644 (file)
index 0000000..9dc32a3
--- /dev/null
@@ -0,0 +1,12 @@
+public class pr29812_injar
+{
+  public class inner
+  {
+  }
+
+  static {
+    System.loadLibrary("pr29812_injar");
+  }
+
+  public static native void doit();
+}