On Oct 4, 2012, at 12:33 AM, David Holmes <[email protected]> wrote:
> On 3/10/2012 11:37 PM, Paul Sandoz wrote: >> On Oct 3, 2012, at 3:17 PM, David Holmes<[email protected]> wrote: >>> On 3/10/2012 10:50 PM, Paul Sandoz wrote: >>>> For the benefit of others; for some context see this recent thread: >>>> >>>> http://markmail.org/search/?q=openjdk#query:openjdk%20list%3Anet.java.openjdk.core-libs-dev%20order%3Adate-backward+page:2+mid:inod424lqbey5fms+state:results >>>> >>>> Basically ServiceLoader is treating a null CL parameter as the system CL >>>> for loading the META-INF/services resources file and as the bootstrap CL >>>> for loading the classes of class names declared in those resource files. >>>> >>>> Which also means that calls to: >>>> >>>> ServiceLoader.load(serviceInterface) >>>> ServiceLoader.load(serviceInterface, >>>> Thread.currentThread().getContextClassLoader()); >>>> >>>> Will behave oddly if the TCCL is null, from the JavaDoc of >>>> Thread.getContextClassLoader(): >>>> >>>> >>>> http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#getContextClassLoader() >>>> Returns: >>>> the context ClassLoader for this Thread, or null indicating the system >>>> class loader (or, failing that, the bootstrap class loader) >>> >>> The @return doc for getContextClassLoader is wrong, or at best mis-leading. >>> A null return does NOT indicate the system class loader (which is never >>> null) - it simply means there is no CCL for that thread. If anything null >>> would represent the bootstrap loader. >> >>> >> >> In the JDK i see code such as: >> >> Class c = Class.forName(className, >> true,Thread.currentThread(). >> getContextClassLoader()); >> >> and: >> >> ClassLoader contextClassLoader = >> Thread.currentThread().getContextClassLoader(); >> if (contextClassLoader == null) { >> contextClassLoader = ClassLoader.getSystemClassLoader(); >> } >> >> The only way i can interpret that TCCL JavaDoc sanely is to assume "null" is >> overloaded to mean the caller should try to use system or bootstrap CL if >> possible, otherwise failing that the bootstrap CL. > > The TCCL doc for @return is simply confusing. > The method will return the TCCL or it will return null. If it returns null it > means the Thread has no CCL set. So what does a caller then do? They have a > few choices: > a) use their own ClassLoader > b) use the system ClassLoader > c) use the the bootstrap loader > > Your first example chooses (c) because the null arg to forName will indicate > to use the bootstrap loader. Your second example chooses (b). This is not an > arbitrary choice as it depends on the API - the three arg version of forName > treats null as the bootstrap loader, but if you simply did > getContextClassLoader().loadClass(...) then you would get NPE. > > The point is that returning null in itself has no direct significance. I am not sure i agree. The TCCL can be set to null and that has significance as per the JavaDoc: * @param cl * the context ClassLoader for this Thread, or null indicating the * system class loader (or, failing that, the bootstrap class loader) * * @throws SecurityException * if the current thread cannot set the context ClassLoader * * @since 1.2 */ public void setContextClassLoader(ClassLoader cl) { Paul. > The issue here is how ServiceLoader should attempt to load something if there > is no CCL set for the thread. >
