我想编写一个自定义类加载器,从自定义网络跨越加载一个JAR
文件。最终,我只需使用一个JAR
文件的字节数组。
我无法将字节数组转储到文件系统并使用URLClassLoader
。
我的第一个计划是从流或字节数组创建一个JarFile
对象,但它只支持File
对象。
我已经编写了一个使用JarInputStream
的东西:
public class RemoteClassLoader extends ClassLoader {
private final byte[] jarBytes;
public RemoteClassLoader(byte[] jarBytes) {
this.jarBytes = jarBytes;
}
@Override
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(name);
if (clazz == null) {
try {
InputStream in = getResourceAsStream(name.replace('.', '/') + ".class");
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamUtils.writeTo(in, out);
byte[] bytes = out.toByteArray();
clazz = defineClass(name, bytes, 0, bytes.length);
if (resolve) {
resolveClass(clazz);
}
} catch (Exception e) {
clazz = super.loadClass(name, resolve);
}
}
return clazz;
}
@Override
public URL getResource(String name) {
return null;
}
@Override
public InputStream getResourceAsStream(String name) {
try (JarInputStream jis = new JarInputStream(new ByteArrayInputStream(jarBytes))) {
JarEntry entry;
while ((entry = jis.getNextJarEntry()) != null) {
if (entry.getName().equals(name)) {
return jis;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
对于小的JAR
文件,这可能很好用,但我尝试加载一个大小为2.7MB
、几乎包含2000
个类的jar文件时,仅遍历所有条目就需要160毫秒
,更别说加载它找到的类了。如果有人知道比每次加载类时都遍历JarInputStream
条目更快的解决方案,请分享!