|
I wonder if separate application deployment class definitions are being created by the TcclSafeAggregatedClassLoader. From looking at the TcclSafeAggregatedClassLoader code in org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl, it looks like we are passing the TCCL (thread context classloader) to the TcclSafeAggregatedClassLoader super class (JDK ClassLoader impl) constructor:
private class TcclSafeAggregatedClassLoader extends ClassLoader {
private final AggregatedClassLoader aggregatedClassLoader;
private TcclSafeAggregatedClassLoader(AggregatedClassLoader aggregatedClassLoader, ClassLoader tccl) {
super(tccl);
this.aggregatedClassLoader = aggregatedClassLoader;
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
return aggregatedClassLoader.getResources( name );
}
@Override
protected URL findResource(String name) {
return aggregatedClassLoader.findResource( name );
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return aggregatedClassLoader.findClass( name );
}
}
Without the change, we were just setting the TCCL to be an instance of AggregatedClassLoader. The AggregatedClassLoader passes null to the super class constructor:
private static class AggregatedClassLoader extends ClassLoader {
private ClassLoader[] individualClassLoaders;
private AggregatedClassLoader(final LinkedHashSet<ClassLoader> orderedClassLoaderSet) {
super( null );
individualClassLoaders = orderedClassLoaderSet.toArray( new ClassLoader[orderedClassLoaderSet.size()] );
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
final LinkedHashSet<URL> resourceUrls = new LinkedHashSet<URL>();
for ( ClassLoader classLoader : individualClassLoaders ) {
final Enumeration<URL> urls = classLoader.getResources( name );
while ( urls.hasMoreElements() ) {
resourceUrls.add( urls.nextElement() );
}
}
return new Enumeration<URL>() {
final Iterator<URL> resourceUrlIterator = resourceUrls.iterator();
@Override
public boolean hasMoreElements() {
return resourceUrlIterator.hasNext();
}
@Override
public URL nextElement() {
return resourceUrlIterator.next();
}
};
}
@Override
protected URL findResource(String name) {
for ( ClassLoader classLoader : individualClassLoaders ) {
final URL resource = classLoader.getResource( name );
if ( resource != null ) {
return resource;
}
}
return super.findResource( name );
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for ( ClassLoader classLoader : individualClassLoaders ) {
try {
return classLoader.loadClass( name );
}
catch (Exception ignore) {
}
}
throw new ClassNotFoundException( "Could not load requested class : " + name );
}
public void destroy() {
individualClassLoaders = null;
}
}
With the latest 4.3 branch code, does changing the TcclSafeAggregatedClassLoader constructor to the following, have any impact?
private TcclSafeAggregatedClassLoader(AggregatedClassLoader aggregatedClassLoader, ClassLoader tccl) {
super(null);
this.aggregatedClassLoader = aggregatedClassLoader;
}
If yes, we can try to explain why this change was made. At the moment, I'm not sure if its the important difference between TcclSafeAggregatedClassLoader and the AggregatedClassLoader.
|