我有一个简单的插件系统,可以将外部JAR插件加载到主应用程序中。我正在使用Mountainblade Modular这样做。不确定他们是如何做到的“引擎盖下”但可能它是标准的东西。
这很好用,我从外部jar实例化类,这一切都有效。除了一些插件附带图标/图像。我有点不确定如何从外部JAR加载/引用图像(在外部JAR中包含代码,因为它在主JAR的上下文中运行,有点类似)
我该如何处理?
答案 0 :(得分:1)
这个问题并不像看起来那么简单。
从外部jar加载类时,它们被“加载”到JVM中。通过“加载”到JVM中,我的意思是JVM负责它们在内存中的存储。通常它是这样完成的:
ClassLoader myClassLoader = new MyClassLoader(jarFileContent);
Class myExtClass = myClassLoader.loadClass(myClassName);
使用
可以轻松访问classpath jar中的资源InputStream resourceStream = myClass.getResourceAsStream("/myFile.txt");
你可以这样做,因为这些罐子在类路径中,我的意思是它们的位置是已知的。这些文件不存储在内存中。访问资源时,JVM可以在类路径jar中搜索它(例如在文件系统上)。
但对于外部罐子来说,它完全不同:罐子来自无处,经过处理和遗忘。 JVM不会从内存中加载资源。要访问这些文件,您必须手动组织其存储。我已经完成了这一次,所以我可以分享代码。它将帮助您理解基本概念(但可能无法帮助您使用特定的库)。
// Method from custom UrlClassLoader class.
// jarContent here is byte array of loaded jar file.
// important notes:
// resources can be accesed only with this custom class loader
// resource content is provided with the help of custom URLStreamHandler
@Override
protected URL findResource(String name) {
JarInputStream jarInputStream;
try {
jarInputStream = new JarInputStream(new ByteArrayInputStream(jarContent));
JarEntry jarEntry;
while (true) {
jarEntry = jarInputStream.getNextJarEntry();
if (jarEntry == null) {
break;
}
if (name.equals(jarEntry.getName())) {
final byte[] bytes = IOUtils.toByteArray(jarInputStream);
return new URL(null, "in-memory-bytes", new URLStreamHandler() {
@Override
protected URLConnection openConnection(URL u) throws IOException {
return new URLConnection(u) {
@Override
public void connect() throws IOException {
// nothing to do here
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(bytes);
}
};
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}