Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4122610

native method linking doesn't work for user-defined classloader

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Duplicate
    • Affects Version/s: 1.1, 1.1.4, 1.1.5, 1.1.6, 1.2.0
    • Fix Version/s: None
    • Component/s: hotspot
    • Subcomponent:
    • CPU:
      sparc
    • OS:
      solaris_2.4

      Description



      Name: akC45999 Date: 03/25/98



      The following test shows that JVM cannot link native methods to classes
      loaded with user-defined classloader.

      As a result, all our Java Native Interface tests and
      some other VM test fail in same-jvm mode.

      To run the test, copy following 4 files in a working directory,
      edit shell-script runtest to reflect actial path to your installation of JCK
      (used only to find include files) and run the script.
      The script compiles c and java files, runs the test with
      default classloader to verify installation, and runs the
      test via user-defined classloader.

      ============================================================ gver00101.c
      /* File: @(#)gver00101.c 1.2 97/01/27
         Copyright 01/27/97 Sun Microsystems, Inc. All Rights Reserved
      */

      #include <stdlib.h>
      #include <string.h>
      #include <stdio.h>
      #include "jckjni.h"

      #ifdef __cplusplus
      extern "C" {
      #endif

      #ifdef __cplusplus
      #ifndef JNI_ENV_ARG1
      #define JNI_ENV_ARG1(x)
      #define JNI_ENV_PTR(x) x
      #endif
      #else
      #ifndef JNI_ENV_ARG1
      #define JNI_ENV_ARG1(x) x
      #define JNI_ENV_PTR(x) (*x)
      #endif
      #endif





      JNIEXPORT jboolean JNICALL
      /*Java_javasoft_sqe_tests_vm_gver001_gver00101_gver00101_gver00101nm*/
      Java_gver00101_gver00101nm
      (JNIEnv *env,jobject obj,
      jint val)
       {
      jint res_val;

      res_val = JNI_ENV_PTR(env) -> GetVersion(JNI_ENV_ARG1(env));
      return !(res_val==val);
       }


      #ifdef __cplusplus
      }
      #endif

      ============================================================ gver00101.java
      //File: @(#)gver00101.java 1.3 97/08/25
      //Copyright 08/25/97 Sun Microsystems, Inc. All Rights Reserved

      //package javasoft.sqe.tests.vm.gver001.gver00101;
      import java.io.PrintStream;

      public class gver00101 {

        private static boolean res = false;

        public static void main(String argv[])
        {
           System.exit(run(argv, System.out) + 95/*STATUS_TEMP*/);
        }

        public native boolean gver00101nm(int val);

        static {
          try {
            loadLib("gver00101");
          } catch ( UnsatisfiedLinkError e ) {
            System.out.println("gver00101.static:"+e);
          }

        }
        
        private static void check( gver00101 tob, int val) {
          try {
            boolean res= tob.gver00101nm(val);
            System.out.println("res="+res);
          } catch (Throwable e) {
            res = true;
            System.out.println("Exception caught: "+e);
          }
        }

        static void loadLib( String libName ) {
      SecurityManager mgr = System.getSecurityManager();
      boolean canLoad = true;
      linkStatus=2/*STATUS_FAILED*/;

      if( mgr != null ) {
      try {
      mgr.checkLink( libName );
      } catch (SecurityException e) {
      canLoad = false;
      }
      }
          
      try {
      System.loadLibrary( libName );
      if (canLoad) {
      cannotBeRun = null;
      } else {
      cannotBeRun = "Incorrectly loaded library: " + libName;
      }
      } catch (SecurityException e) {
      if (!canLoad) {
      linkStatus = 0/*STATUS_PASSED*/;
      cannotBeRun = "Correctly prevented loadLibrary: " + libName;
      } else {
      cannotBeRun = "Incorrectly prevented loadLibrary: " + libName;
      }
      } catch (UnsatisfiedLinkError e) {
      cannotBeRun = "Cannot find library: " + libName;
      throw e;
      }
        }

        static String cannotBeRun;
        static int linkStatus;

        public static int run(String argv[], PrintStream out) {
      if (cannotBeRun!=null) {
      out.println(cannotBeRun);
      return linkStatus;
      }
          gver00101 tob = new gver00101();
          int valVer = 0x00010001;

          check( tob, valVer );

          if (res)
            return 2/*STATUS_FAILED*/;
          return 0/*STATUS_PASSED*/;
        }
      }

      ============================================================ TestWrapper.java
      import java.io.*;
      import java.lang.reflect.*;

      class TestWrapper extends ClassLoader {
          File store;
          TestWrapper(File store) {
              this.store=store;
          }

          void debug(String msg) {
       // System.out.println(msg);
          }

          byte readClass(String className)[] {
              byte result[];
              try {
                  FileInputStream fi
                      = new FileInputStream(new File(store, className+".class"));
                  result = new byte[fi.available()];
                  fi.read(result);
                  debug(" >> readClass("+className+") OK");
                  return result;
              } catch (Exception e) {
                  debug(" >> readClass("+className+"):"+e);
                  return null;
              }
          }

          public Class loadClass(String className, boolean resolve) throws
      ClassNotFoundException {
             Class result;
              byte classData[];

              debug("> Load class : "+className);

              /* Try to load it from our repository */
              classData = readClass(className);
              if (classData == null) {
               /* Check with the primordial class loader */
                  result = super.findSystemClass(className);
                  debug(" >> returning class in CLASSPATH.:"+result);
                  return result;
              }

              /* Define it (parse the class file) */
              result = defineClass(classData, 0, classData.length);
              if (result == null) {
                  throw new ClassFormatError();
              }

              debug(" >> Returning newly loaded class:"+className);
              return result;
          }

       public static void runClass(Class executeClass) {
      PrintStream out=System.out;
      Class[] argTypes = {String[].class, PrintStream.class};
      Method runMethod = null;
      try {
      runMethod = executeClass.getDeclaredMethod("run", argTypes);
      } catch (SecurityException e) {
      out.println("While looking for run() method in the test class " +
      executeClass + "\nSecurityException arose: " + e);
      return;
      } catch (NoSuchMethodError e) {
      out.println("run() not found in the test class " + executeClass);
      return;
      } catch (NoSuchMethodException e) {
      out.println("run() not found in the test class " + executeClass);
      return;
      } catch (Throwable e) {
      out.println("Unexpected exception on executeClass.getDeclaredMethod()
      invocation: " + e);
      return;
      }

      Object[] args={null, out};

      try {
      Integer result = (Integer)runMethod.invoke(null, args);
      out.println("TestWrapper.runClass: result=" + result.intValue());
      } catch (ClassCastException e) {
      out.println("run() must return an int value in the test class " +
      executeClass);
      } catch (NullPointerException e) {
      out.println("run() must be static in the test class " + executeClass);
      } catch (IllegalAccessException e) {
      out.println("run() is not accessible in the test class " + executeClass);
      } catch (InvocationTargetException e) {
      Throwable ee = e.getTargetException();
      out.println("TestWrapper.runClass:runtime exception: " + ee);
      } catch (Throwable e) {
      out.println("Unexpected exception on runMethod.invoke() invocation: " +
      e);
      }

       }

        public static void test(String argv[]) {
              System.out.println("========TestWrapper.test("+argv[0]+ ","+argv[1]+")");
              File store=new File(argv[0]);
              TestWrapper sc = new TestWrapper(store);
      Class executeClass;
              try {
                  executeClass=sc.loadClass(argv[1]);
              } catch (Throwable e) {
                  System.out.println("TestWrapper.loadClass:"+e);
      return;
              }
      runClass(executeClass);
        }

        public static void main(String argv[]) {
              test(argv);
              test(argv);
              test(argv);
        }

      }
      ========================================================== runtest
      #!/bin/sh

      rm -rf *.so *class store

      #CC=/export/ld4/set/dist/sparc-S2/SC4.2/bin/cc
      CC=cc

      # set JCK to the path to your JCK workspace
      JCK=/export/ld21/java/sqe/jck116/jck11-nsk/port

      cmd="$CC -KPIC -G -o libgver00101.so -I$JCK/tests/vm/jni/include
      -I$JCK/tests/vm/jni/include/solaris -I/include -I/include/solaris gver00101.c"
      echo $cmd; eval $cmd

      LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
      CLASSPATH=store
      export LD_LIBRARY_PATH CLASSPATH

      mkdir store
      cmd="javac TestWrapper.java"
      echo $cmd; eval $cmd
      cmd="javac -d store gver00101.java"
      echo $cmd; eval $cmd

      java gver00101

      CLASSPATH=.
      export CLASSPATH
      cmd="java TestWrapper store gver00101"
      echo $cmd; eval $cmd
      ============================================================

      when run under jdk1.1.x, test throws UnsatisfiedLinkError each time
      it is run:

      novo64% runtest
      cc -KPIC -G -o libgver00101.so
      -I/export/ld21/java/sqe/jck116/jck11-nsk/port/tests/vm/jni/include
      -I/export/ld21/java/sqe/jck116/jck11-nsk/port/tests/vm/jni/include/solaris
      -I/include -I/include/solaris gver00101.c javac TestWrapper.java
      Note: TestWrapper.java uses a deprecated API. Recompile with "-deprecation"
      for details. 1 warning
      javac -d store gver00101.java
      res=false
      java TestWrapper store gver00101
      ========TestWrapper.test(store, gver00101)
      Exception caught: java.lang.UnsatisfiedLinkError: gver00101nm
      TestWrapper.runClass: result=2
      ========TestWrapper.test(store, gver00101)
      Exception caught: java.lang.UnsatisfiedLinkError: gver00101nm
      TestWrapper.runClass: result=2
      ========TestWrapper.test(store, gver00101)
      Exception caught: java.lang.UnsatisfiedLinkError: gver00101nm
      TestWrapper.runClass: result=2

      when run under jdk1.2 (including the latest current release 12beta3N),
      test passes first time but throws UnsatisfiedLinkError
      for consequent calls of TestWrapper.test() method:

      novo64% jdk12
      novo64% runtest
      cc -KPIC -G -o libgver00101.so
      -I/export/ld21/java/sqe/jck116/jck11-nsk/port/tests/vm/jni/include
      -I/export/ld21/java/sqe/jck116/jck11-nsk/port/tests/vm/jni/include/solaris
      -I/include -I/include/solaris gver00101.c javac TestWrapper.java
      Note: TestWrapper.java uses or overrides a deprecated API. Recompile with
      "-deprecation" for details. 1 warning
      javac -d store gver00101.java
      res=true
      java TestWrapper store gver00101
      ========TestWrapper.test(store, gver00101)
      res=true
      TestWrapper.runClass: result=0
      ========TestWrapper.test(store, gver00101)
      gver00101.static:java.lang.UnsatisfiedLinkError: Native Library
      /export/home/rfq/ws/bugexamples/NewFolder.2/libgver00101.so already loaded in
      another classloader Cannot find library: gver00101
      TestWrapper.runClass: result=2
      ========TestWrapper.test(store, gver00101)
      gver00101.static:java.lang.UnsatisfiedLinkError: Native Library
      /export/home/rfq/ws/bugexamples/NewFolder.2/libgver00101.so already loaded in
      another classloader Cannot find library: gver00101
      TestWrapper.runClass: result=2
      novo64%

      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                apalanissunw Anand Palaniswamy (Inactive)
                Reporter:
                rfqsunw Rfq Rfq (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: