Weijun Wang said the following on 08/08/11 13:34:
On 08/08/2011 10:46 AM, David Holmes wrote:
Weijun Wang said the following on 08/06/11 00:19:
I have two files: A.java and B.java
/*
* @test
* @build A B
* @run main A
*/
public class A {
public static void main(String[] args) throws Exception {
Class.forName("B", true,
Thread.currentThread().getContextClassLoader());
}
}
public class B {
}
Now jtreg A.java shows:
java.lang.ClassNotFoundException: B
How can I get B visible in A's ContextClassLoader?
It isn't A's context class loader it is the current threads. If the
above isn't working then either:
a) A is not being loaded by the application (aka system) classloader
(jtreg is using a custom loader); or
b) jtreg has explicitly changed the current thread's context classloader
You would need to investigate what A.class.getClassLoader() reports, and
what Thread.currentThread().getContextClassLoader() reports.
A.class.getClassLoader(): A URLClassLoader looking at
JTwork/classes/test_location and $TESTSRC.
Thread.currentThread().getContextClassLoader(): A
sun.misc.Launcher$AppClassLoader looking at jtreg.jar. It is also the
parent class loader of A.class.getClassLoader().
BTW, I've added
Thread.currentThread().setContextClassLoader(
A.class.getClassLoader());
to the test to make it pass.
Right. The default context loader for a thread is that of the creating
thread, and the default for the main thread is the app loader. So if you
then use a custom loader, as here, to load A, then the context loader
won't be able to find B. You have to update the context loader as well.
Of course in this simple example it is somewhat pointless to set the
context loader to fix the problem as you can just use the requisite
class loader in the first place.
Don't tell me to change to Class.forName("B"), that line is copied
from JDK that is called by a real test.
Or, the JDK code itself is problematic and it should fallback to
another ClassLoader?
It's unclear why the code/test needs to use the context classloader here
(or why/how it knows the context loader is the correct loader).
I'm not sure.
It's probably more important to determine the answer to this question.
The context class loader is really only meant to be used by SPI
frameworks so that the core service code (loaded by the extensions
loader) can find the actual service implementation class (without
requiring it to be on the boot or extensions classpath).
Cheers,
David
Thanks
Max
Cheers,
David
Thanks
Max