从外部JAR读取图像

时间:2016-04-17 09:23:16

标签: java plugins jar

我有一个简单的插件系统,可以将外部JAR插件加载到主应用程序中。我正在使用Mountainblade Modular这样做。不确定他们是如何做到的“引擎盖下”但可能它是标准的东西。

这很好用,我从外部jar实例化类,这一切都有效。除了一些插件附带图标/图像。我有点不确定如何从外部JAR加载/引用图像(在外部JAR中包含代码,因为它在主JAR的上下文中运行,有点类似)

我该如何处理?

1 个答案:

答案 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;
}