所以在我的应用程序中我有一个插件系统,我用SPI(服务提供程序接口)编写,所以我有一个名为scripts.jar的jar文件,我保留在某处(注意:它不在类路径上),然后我使用这种方法从中加载脚本:
/**
* Loads a script from the given name, regardless of case.
* @param name script name
* @return the loaded Script
*/
public static Script loadScript(Client c, String name) {
Script script = null;
try {
URLClassLoader loader = new URLClassLoader(new URL[]{new File(Config.CONF_DIR, "scripts.jar").toURI().toURL()});
ServiceLoader serviceLoader = ServiceLoader.load(Script.class, loader);
serviceLoader.reload();
Iterator<Script> scripts = serviceLoader.iterator();
while(scripts.hasNext()) {
Script cur = scripts.next();
if(cur.getClass().getSimpleName().equalsIgnoreCase(name)) {
script = cur;
break;
}
}
} catch(Exception e) {
log.warn("Error loading script "+name, e);
}
return script;
}
现在,当我开始我的程序时,这非常有效。我可以轻松地在jar中加载任何脚本。
当我重新加载脚本时出现问题 - 即更改文件,并覆盖scripts.jar,然后尝试加载任何脚本。我收到这个错误:
Exception in thread "anjin_san:test" java.util.ServiceConfigurationError: org.stork.script.Script: Error reading configuration file
at java.util.ServiceLoader.fail(ServiceLoader.java:207)
at java.util.ServiceLoader.parse(ServiceLoader.java:284)
at java.util.ServiceLoader.access$200(ServiceLoader.java:164)
at java.util.ServiceLoader$LazyIterator.hasNext(ServiceLoader.java:332)
at java.util.ServiceLoader$1.hasNext(ServiceLoader.java:415)
at org.stork.script.Script.loadScript(Script.java:408)
at org.stork.Client$2.run(Client.java:95)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.io.FileNotFoundException: JAR entry META-INF/services/org.stork.script.Script not found in C:\Users\stork\Documents\bot-sama\etc\scripts.jar
at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:122)
at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:132)
at java.net.URL.openStream(URL.java:1010)
at java.util.ServiceLoader.parse(ServiceLoader.java:279)
... 6 more
所以它说无法找到jar条目,但我可以很容易地检查它:
C:\Users\stork\Documents\bot-sama\etc>jar tvf scripts.jar
0 Thu Sep 03 16:58:00 BST 2009 META-INF/
102 Thu Sep 03 16:57:58 BST 2009 META-INF/MANIFEST.MF
0 Thu Sep 03 16:35:20 BST 2009 META-INF/services/
482 Thu Sep 03 16:57:52 BST 2009 META-INF/services/org.stork.script.Script
...
它也是合适的尺寸。当我尝试加载任何脚本时,问题就发生了,而不仅仅是那个被修改过的脚本。
我认为这可能是一个错误,任何输入?
答案 0 :(得分:4)
检查文件权限。当原始JAR与应用程序的其余部分放在一起时,程序可以读取它。也许它被不同的用户更新 - 而不向其他用户授予读取权限 - 并且程序无法再打开该文件。
我无法分辨您正在运行的Windows版本,但是安全属性对话框,或者在XP Home上,cacls
命令应详细说明之前和之后的权限。
更新:重新阅读ServiceLoader
文档,我注意到了一个实例方法reload
。虽然代码每次需要时都会创建一个新的ServiceLoader
,但可能是ServiceLoader
类保留了所有实例使用的缓存。不要创建新的加载器,而是尝试保留一个,并使用reload
方法检查新脚本。
答案 1 :(得分:0)
正如comment in another answer所说,禁用URL连接中的缓存对我有用,但在我的解决方案中,我没有调用openConnection()
方法。相反,我称之为以下方法:
private void disableURLConnectionCache() {
new URLConnection(null) {
@Override
public void connect() throws IOException {}
}.setDefaultUseCaches(false);
}