2

Edit: this is the Project Setup:

IDE: Eclipse:

Project1 : "Server"

src:
com/mainpackage/main.java
libs:
commons-x-0.jar
PluginInterface.jar

all jar in libs-folder are on the buildpath.

Project2 : "PluginInterface"

src:
com/interfaces/plugininterface

Project3 : "Plugin"

src:
com/package/class1.java - (this implements plugininterface)
libs:
library1.jar
PluginInterface.jar

all jar in libs-folder are on the buildpath

so when i export the Plugin (Project3) i get a jar like this (excluded PluginInterface.jar from export)

com/
com/package/
com/package/class1.class
com/package/class1.java
libs/
libs/library1.jar

library1.jar looks as follows - it is not written by me:

com/
com/stuff/
com/stuff/libclass.java
com/stuff/libclass.class

now i Want to utilize class1 in the "Server" over the Interface:

ClassLoader loader=URLClassLoader.newInstance( 
                new URL[]{new URL("file:path/to/plugin.jar")},
                ClassLoader.getSystemClassLoader()
        );

Class<?> pluginclass = Class.forName("com.package.class1", true, loader);
plugininterface ref = (plugininterface)pluginclass.newInstance();

i can now call methods from class1 using the interface both projects know, because both of them include "PluginInterface.jar" in their buildpath.

THE PROBLEM:

"Server" does not recognize "libclass", because is neither in its path nor did i load the class from the plugin.jar in which the library1 is nested.

how do i access this class if an import as library is not possible at the server?

Thanks for any help!

Edit: just for the sake if someone ever has this Problem again, i'll add the ANT files' build-target that makes it work:

<target name="build">
     <javac destdir="bin" includeantruntime="false" source="1.7" target="1.7">
        <src path="src"/>
        <classpath refid="Plugin.classpath"/>
     </javac>
    <unzip src="${libs}/library1.jar" dest="bin/">
        <patternset>
            <include name="**/*.class"/>
        </patternset>
</unzip>
    <jar destfile="plugin.jar" basedir="bin"></jar> 
</target>

Just copy the contents of the Library-jar into the build directory (in my case ./bin/). it then isn't even necessary to feed the libraryclasses to the Classloader, it finds them when loading the Classes use them.

4

2 回答 2

11

标准类加载器不支持嵌套的 jar 文件。您可以以编程方式提取 jar,或编写您自己的类加载器,它将按需解压缩嵌套文件。但是,您将逆流而上:不建议使用这种包装。相反,建议将嵌套 jar 分解为其父级。例如,这是 Maven 依赖插件所做的,以及使用 Leiningen 发布 Clojure 应用程序的默认方式。

为了从 Eclipse 中实现您的目标,最好的方法似乎是:

  1. 让 Eclipse 的导出 JAR 向导保存它内部生成的 ant 构建脚本以构建您的 JAR;

  2. 调整生成的脚本以满足您的特定需求;

  3. 以后不再运行向导,而是运行 ant 脚本。

于 2013-06-24T12:00:25.080 回答
0

正如 Marko 所提到的,您的标准类加载器不会扫描嵌套 jar 和其中的嵌套 jar。但是,如果您愿意使用TrueZip,您可以轻松地做到这一点,而无需提取档案或任何东西。更好的是,您可以在嵌套档案中拥有任意深度的嵌套档案。所以你的路径可能看起来像:

/path/to/foo.jar/bar/foo/my.zip/containing/some.tar/com/foo/My.class

如果你觉得使用 TrueZip 编写自己的类加载器很舒服,这将是一个很好的方法。如果没有,那么您必须编写一个实用程序类来解析路径并首先提取档案,然后再将其输入标准URLClassloader.

于 2013-07-01T14:37:46.303 回答