【问题标题】:Reading images from external JAR从外部 JAR 读取图像
【发布时间】:2016-04-17 09:23:16
【问题描述】:

我有一个简单的插件系统,它将外部 JAR 插件加载到主应用程序中。我正在使用Mountainblade Modular 这样做。不知道他们是如何“在幕后”做到的,但可能是标准的。

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

我应该如何处理这个问题?

【问题讨论】:

  • JAR 文件相对于你的类路径在哪里?
  • 我不太确定这个解决方案,虽然如果 ABC 是你的班级,那么 ABC.class.getClassLoader.getResource() 可能会帮助你
  • @TimBiegeleisen 基本上在构建主主应用程序 jar 时,它附近有 plugins 文件夹,其他外部 jar 在 plugins 文件夹中。

标签: java plugins jar


【解决方案1】:

这个问题并不像看起来那么简单。

当您从外部 jar 加载类时,它们会被“加载”到 JVM 中。通过“加载”到 JVM 中,我的意思是 JVM 负责将它们存储在内存中。通常是这样完成的:

ClassLoader myClassLoader = new MyClassLoader(jarFileContent);
Class myExtClass = myClassLoader.loadClass(myClassName);

类路径 jar 中的资源可以通过以下方式轻松访问

InputStream resourceStream = myClass.getResourceAsStream("/myFile.txt");

您可以这样做,因为这些 jar 在类路径中,我的意思是它们的位置是已知的。这些文件不存储在内存中。当资源被访问时,JVM 可以在类路径 jar 中搜索它(例如在文件系统上)。

但对于外部 jar 则完全不同: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;
}

【讨论】:

    猜你喜欢
    • 2015-06-30
    • 1970-01-01
    • 2012-01-30
    • 2015-11-30
    • 2012-10-28
    • 2013-04-01
    • 2013-12-08
    • 2015-12-23
    相关资源
    最近更新 更多