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

JNI spec clarification: FindClass() returns null on non-system classes in JAR files

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P5 P5
    • 6
    • 5.0
    • hotspot
    • b95
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.4.2_04"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
      Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      When I invoke FindClass() on system classes it works fine. However, when I try invoking FindClass() on one of my own classes that is located within a JAR file, it fails. The JAR file is in the classpath and the native code invoking FindClass() is itself a class located within the same class file.

      To clarify: class A is a non-system class with native methods and is located in the JAR file. One of its native methods invokes FindClass() on class B, which is also found in the JAR file. The former loads fine, the latter fails. The only difference I can think of is that class A is loaded by Java code while class B is loaded by native code.

      However, according to http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#wp16027 because class A native method has the JAR classloader, class B should load just fine using the same classloader.

      Please let me know if I misunderstood how FindClass() functions. And, at the very least, update JDK 1.4 and JDK 1.5 JNI documentation with more verbose explanations as found here: http://java.sun.com/docs/books/jni/html/functions.html#52110

      The latter document is much clearer on which classloader is expected to be used for native methods.


      REPRODUCIBILITY :
      This bug can be reproduced always.
      Hi Karen,

      To recap:

      1) When I look up a class from within Java code and that class is
      packaged inside a JAR, it resolves fine.

      2) When I look up a class from within C/C++ code and that class is
      packaged inside a JAR, it fails to resolve.

      The verbose documentation you mentioned hints at this:

      "In Java 2 SDK release 1.2, FindClass locates the class loader
      associated with the current native method. If the native code belongs to
      the null loader, then it uses the bootstrap class loader to load the
      named class or interface."

      To my understanding, the reason that FindClass() fails in #2 is that
      the bootstrap class loader does not have the ability to look inside JARs
      and the developer would have to explicitly tell JNI to use the JAR
      classloader before using FindClass().

      I would recommend the following actions to resolve this issue:

      1) The documentation says "FindClass locates the class loader associated
      with the current native method" but it does not discuss how one
      associates a particular class-loader with a native method. Is this
      configurable? How does a developer know which class-loader is associated
      with the method? The documentation should discuss this more explicitly.

      In my particular use-case, class A was contained within a JAR file so it
      must have been loaded by JARClassLoader. Then class A had a native
      method and when that native method was invoked I was expecting it to be
      associated with the JARClassLoader but it turns out it was associated
      with the bootstrap class-loader for an unknown reason, which is why I
      could not invoke FindClass() from within that method to find class B
      which was also contained within the same JAR. This was confusing. I was
      expecting that class A would be able to find class B since both are
      contained within the same JAR file and since class A was loaded using
      the same class-loader than class B could be found with. Do you see what
      I mean?

      2) Make the documentation more explicit: "When executing native code
      contained within JAR files or executing within Webstart, the developer
      must instead invoke ClassLoader.loadClass() on the JARClassLoader or
      Webstart class-loader, respectively. The bootstrap class-loader will
      fail to look up classes under these conditions."

      This is just roughly speaking what I expect to read. I'm sure you can
      rephrase it in a more elegant manner.

      3) I expect to find a hyperlink right after the description for
      FindClass() found here:
      http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/functions.html#wp16027
      and this should link directly to
      http://java.sun.com/docs/books/jni/html/functions.html#52110

      4) FindClass()'s description in
      http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/functions.html#wp16027
      is misleading because it says "It searches the directories and zip
      files" and in my experience, the latter is not true.

      5) I think the biggest problem is using FindClass() under Webstart.
      Developers are expecting to be able to take a standalone Java
      application, wrap it using Webstart and deploy it. No one expects that
      Webstart uses a custom class-loader which breaks the way native code
      works so a lot of work needs to go into documenting this better so
      developers know how to code in a manner that is portable across Webstart
      and stand-alone applications.

      I think it would be useful to add a section to
      http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/contents.html
      which explicitly discusses Webstart's custom classloader and its impacts
      on JNI code (i.e. "how to write JNI code which is Webstart-safe").

      If you have any further questions do not hesitate to ask again

      Thank you,
      Gili

            sbohne Steve Bohne (Inactive)
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: