Help: ContextClassLoader in jtreg tests

David Holmes David.Holmes at oracle.com
Mon Aug 8 03:42:46 UTC 2011


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



More information about the core-libs-dev mailing list