Isolatingclassloader
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* used to isolated classes
*/
public class IsolatingClassLoader extends ClassLoader {
private final Map<String, Class> cache = new ConcurrentHashMap<String, Class>();
private final IsolationFilter isolationFilter;
public static interface IsolationFilter {
/**
* @param className the name of the class
* @return returns tue if the class should be loaded via the IsolatingClassLoader, otherwise it will be delegated
*/
boolean isIsolated(@NotNull String className);
}
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(IsolatingClassLoader.class);
/**
* @param isolationFilter a filter that true if the class should be loaded via the IsolatingClassLoader, otherwise it will be delegated
*/
public IsolatingClassLoader(@NotNull final IsolationFilter isolationFilter) {
super(IsolatingClassLoader.class.getClassLoader());
this.isolationFilter = isolationFilter;
}
public Class loadClass(String className) throws ClassNotFoundException {
if (LOG.isDebugEnabled())
LOG.debug("loading className=" + className);
return findClass(className);
}
public Class findClass(String className) {
final Class result = cache.get(className);
if (result != null) {
return result;
}
if (!isolationFilter.isIsolated(className))
try {
return findSystemClass(className);
} catch (Exception e) {
// do nothing
}
try {
final byte[] classByte = loadClassData(className);
final Class result0 = defineClass(className, classByte, 0, classByte.length, null);
cache.put(className, result0);
return result0;
} catch (Exception e) {
return null;
}
}
private byte[] loadClassData(String className) throws IOException {
if (LOG.isDebugEnabled())
LOG.debug("loadClassData className=" + className);
final String replacedClass = className.replace(".", "/");
final InputStream resourceAsStream1 = this.getResourceAsStream(replacedClass + ".class");
final ByteArrayOutputStream oStream = new ByteArrayOutputStream(1024);
for (; ;) {
int read = resourceAsStream1.read();
if (read == -1) {
break;
}
oStream.write(read);
}
byte[] bytes1 = oStream.toByteArray();
return bytes1;
}
public Class loadClass(String pClassName, boolean pResolve) throws ClassNotFoundException {
if (LOG.isDebugEnabled())
LOG.debug("loadClass=" + pClassName);
return super.loadClass(pClassName, pResolve);
}
}
and to use it
public class TestIsolation {
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(TestIsolation.class);
@Test
public void test() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
final NonIsolatedInterface[] isolatedInstances = new NonIsolatedInterface[2];
final String name = IsolatedClass.class.getName();
final IsolatingClassLoader.IsolationFilter isolationFilter = new IsolatingClassLoader.IsolationFilter() {
@Override
public boolean isIsolated(@NotNull String className) {
LOG.info("className=" + className);
/// only isolated the IsolatedClass
return className.equals(IsolatedClass.class.getName());//|| className.equals(IsolatedClass2.class.getName());
}
};
for (int i = 0; i < 2; i++) {
final IsolatingClassLoader isolatingClassLoader = new IsolatingClassLoader(isolationFilter);
final Class<?> aClass = Class.forName(name, true, isolatingClassLoader);
// Thread.currentThread().setContextClassLoader(isolatingClassLoader);
final NonIsolatedInterface o = (NonIsolatedInterface) aClass.newInstance();
isolatedInstances[i] = o;
}
final NonIsolatedInterface one = isolatedInstances[0];
final NonIsolatedInterface two = isolatedInstances[1];
// create the bean
final NonIsolatedBean bean = new NonIsolatedBean();
final String message = "a bean that is passed between the isolating instances";
bean.setString(message);
// set one of the isolating instance to the bean
one.setNonIsolatedBean(bean);
// set the other instance to the result of the first bean
two.setNonIsolatedBean(one.getNonIsolatedBean());
LOG.info("result= " + two.toString());
Assert.assertEquals(message, two.toString());
}
}
page revision: 1, last edited: 08 Apr 2011 16:29