创建一个ClassLoader以从字节数组加载JAR文件 [英] Creating a ClassLoader to load a JAR file from a byte array
问题描述
我正在寻找一个自定义类加载器,它将从自定义网络中加载 JAR
文件。最后,我必须使用的是 JAR
文件的字节数组。
I'm looking to write a custom class loader that will load a JAR
file from across a custom network. In the end, all I have to work with is a byte array of the JAR
file.
我无法将字节数组转储到文件系统上并使用 URLClassLoader
。
我的第一个计划是创建 JarFile
来自流或字节数组的对象,但它只支持文件
对象。
I cannot dump the byte array onto the file system and use a URLClassLoader
.
My first plan was to create a JarFile
object from a stream or byte array, but it only supports a File
object.
我已经写了一些使用 JarInputStream
的东西:
I've already written up something that uses a 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
jar文件,几乎 2000
类和它正在花费 160 ms
只是迭代所有条目,更不用说加载它找到的类。
This may work fine for small JAR
files, but I tried loading up a 2.7MB
jar file with almost 2000
classes and it was taking around 160 ms
just to iterate through all the entries let alone load the class it found.
如果有人知道一个解决方案比每次加载一个类时迭代 JarInputStream
的条目更快,请分享!
If anyone knows a solution that's faster than iterating through a JarInputStream
's entries each time a class is loaded, please share!
推荐答案
我将遍历该类一次并缓存条目。我还会看一下URLClassLoader的源代码,看看它是如何做到的。如果失败,将数据写入临时文件并通过普通的类加载器加载。
I would iterate through the class once and cache the entries. I would also look at the source code for URLClassLoader to see how it does it. If that fails, write the data to a temporary file and load it via the normal class loader.
这篇关于创建一个ClassLoader以从字节数组加载JAR文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!