如果没有设置-Djava.ext.dirs,则不会从目录加载Java SPI JAR

时间:2014-03-29 21:51:53

标签: java jar

我无法让服务提供程序接口从同一目录中的另一个JAR加载实现。它只在我使用-Djava.ext.dirs =时有效。在命令行上。它应该没有用吗?

我有以下界面:

package playground;

public interface TestIface {
    public String test();
}

这是在这里实现的:

package playground;

public class TestImpl implements TestIface {
    public String test() {
        return "TEST";
    }
}

这里我尝试加载实现:

package playground;
import java.util.Iterator;
import java.util.ServiceLoader;
public class Lalala {
    public static void main(String[] args) {
        ServiceLoader<TestIface> loader = ServiceLoader.load(TestIface.class);
        Iterator<TestIface> it = loader.iterator();
        while (it.hasNext()) {
            TestIface a = it.next();
            System.out.println(a.test());
        }
        System.out.println("DONE");
    }

}

接口和最后一个类打包在main.jar中,即impl.jar中的实现。 main.jar具有Main类集,impl.jar具有META-INF / services / playground.TestIface文件,其中包含“playground.TestImpl”。两个JAR都在同一目录中。 运行

java -jar main.jar

只打印“DONE”,显然找不到实现。

如果我改为运行

java -Djava.ext.dirs=. -jar main.jar

它还应该打印“TEST”。

我做错了什么?除非我更改java.ext.dirs设置,为什么不加载其他JAR的实现?

1 个答案:

答案 0 :(得分:0)

java.ext.dirs设置会自动将指定目录中找到的所有jar文件添加到主类加载器中,这就是ServiceLoader可以找到并加载TestIface.class的原因(来自Apidocs:& #34;使用当前线程的上下文类加载器为给定的服务类型创建一个新的服务加载器。&#34;)。

但是你不应该使用java.ext.dirs(请参阅here了解其中一个危险)。当您使用java -jar时,您无法使用java -cp来设置类路径(您只能使用其中一个)。这样您就可以选择使用URLClassLoader加载其他广告,然后调用ServiceLoader.load(class from another jar)

提示:要加载其他jar文件,请使用main.jar文件的位置,如this question的答案中所述。其他变量(如启动目录)取决于Java的启动方式和位置,并且很容易导致找不到其他jar文件。