-
Bug
-
Resolution: Fixed
-
P5
-
5.0
-
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
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
- relates to
-
JDK-6437919 Document JNI FindClass issue for Java Web Start
- Resolved
-
JDK-6204384 (cl spec) FindClass() refers to ClassLoader.getBaseClassLoader() which does not exist
- Resolved