【发布时间】:2013-05-12 05:53:35
【问题描述】:
我正在寻找编写一个自定义类加载器,它将通过自定义网络加载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 文件,但我尝试加载一个几乎包含2000 类的2.7MB jar 文件,它花费了160 ms 来遍历所有条目,更不用说加载找到的类。
如果有人知道比每次加载类时迭代 JarInputStream 的条目更快的解决方案,请分享!
【问题讨论】:
-
我在以前从事的一个项目中继承了一个类似的类加载器。那里也非常慢。除此之外,它还让我很头疼。最后学到的教训是除非你真的需要,否则不要使用自定义类加载器。
-
我不得不问......将它存储在文件中有什么问题?我的意思是,罐子可以是任意大小的,将所有加载的罐子永远保存在内存中听起来是一个非常糟糕的主意。这也意味着您将保留 Jar 字节、缓存的条目以及加载的类……您需要支付 3 倍的罚款。
-
@wyr0 您还期望得到一个不会将 jar 的内容存储到文件系统中的答案,即使它更快且可扩展得多?
标签: java arrays jar classloader