HHH-7084 Do not use ClassLoaderServiceImpl classloader as parent classloader for synthetic ClassLoader

This commit is contained in:
Emmanuel Bernard 2012-05-21 10:59:09 +02:00
parent c341a3ba2c
commit 04b62e1a54
2 changed files with 72 additions and 2 deletions

View File

@ -86,7 +86,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
classLoadingClassLoaders.add( hibernateClassLoader ); classLoadingClassLoaders.add( hibernateClassLoader );
classLoadingClassLoaders.add( environmentClassLoader ); classLoadingClassLoaders.add( environmentClassLoader );
this.classClassLoader = new ClassLoader() { this.classClassLoader = new ClassLoader(null) {
@Override @Override
protected Class<?> findClass(String name) throws ClassNotFoundException { protected Class<?> findClass(String name) throws ClassNotFoundException {
for ( ClassLoader loader : classLoadingClassLoaders ) { for ( ClassLoader loader : classLoadingClassLoaders ) {
@ -197,7 +197,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
@Override @Override
public <S> LinkedHashSet<S> loadJavaServices(Class<S> serviceContract) { public <S> LinkedHashSet<S> loadJavaServices(Class<S> serviceContract) {
final ClassLoader serviceLoaderClassLoader = new ClassLoader() { final ClassLoader serviceLoaderClassLoader = new ClassLoader(null) {
final ClassLoader[] classLoaderArray = new ClassLoader[] { final ClassLoader[] classLoaderArray = new ClassLoader[] {
// first look on the hibernate class loader // first look on the hibernate class loader
getClass().getClassLoader(), getClass().getClassLoader(),

View File

@ -0,0 +1,70 @@
package org.hibernate.test.service;
import org.hibernate.service.classloading.internal.ClassLoaderServiceImpl;
import org.junit.Assert;
import org.junit.Test;
import javax.persistence.Entity;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Artem V. Navrotskiy
* @author Emmanuel Bernard <emmanuel@hibernate.org>
*/
public class ClassLoaderServiceImplTest {
/**
* Test for bug: HHH-7084
*/
@Test
public void testSystemClassLoaderNotOverriding() throws IOException, ClassNotFoundException {
Class<?> testClass = Entity.class;
// Check that class is accessible by SystemClassLoader.
ClassLoader.getSystemClassLoader().loadClass(testClass.getName());
// Create ClassLoader with overridden class.
TestClassLoader anotherLoader = new TestClassLoader();
anotherLoader.overrideClass(testClass);
Class<?> anotherClass = anotherLoader.loadClass(testClass.getName());
Assert.assertNotSame( testClass, anotherClass );
// Check ClassLoaderServiceImpl().classForName() returns correct class (not from current ClassLoader).
ClassLoaderServiceImpl loaderService = new ClassLoaderServiceImpl(anotherLoader);
Class<Object> objectClass = loaderService.classForName(testClass.getName());
Assert.assertSame("Should not return class loaded from the parent classloader of ClassLoaderServiceImpl",
objectClass, anotherClass);
}
private static class TestClassLoader extends ClassLoader {
/**
* Reloading class from binary file.
*
* @param originalClass Original class.
* @throws IOException .
*/
public void overrideClass(final Class<?> originalClass) throws IOException {
String originalPath = "/" + originalClass.getName().replaceAll("\\.", "/") + ".class";
InputStream inputStream = originalClass.getResourceAsStream(originalPath);
Assert.assertNotNull(inputStream);
try {
byte[] data = toByteArray( inputStream );
defineClass(originalClass.getName(), data, 0, data.length);
} finally {
inputStream.close();
}
}
private byte[] toByteArray(InputStream inputStream) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int read;
byte[] slice = new byte[2000];
while ( (read = inputStream.read(slice, 0, slice.length) ) != -1) {
out.write( slice, 0, read );
}
out.flush();
return out.toByteArray();
}
}
}