繁体   English   中英

更换jar文件时无法在jar文件中加载资源

[英]Failed to load resources in jar file when jar file is replaced

我遇到java.util.zip.ZipException:存储的块长度无效。

堆栈跟踪如下:

Caused by: java.util.zip.ZipException: invalid stored block lengths
at java.util.zip.InflaterInputStream.read(Unknown Source)
at java.io.FilterInputStream.read(Unknown Source)
at java.io.FilterInputStream.read(Unknown Source)
at java.util.Properties$LineReader.readLine(Unknown Source)
at java.util.Properties.load0(Unknown Source)
at java.util.Properties.load(Unknown Source)

当我的项目尝试升级时会发生这种情况。 升级逻辑是用新的jar文件替换旧的jar文件,JVM仍然在运行。

jar文件(jarA.jar)包含属性文件,属性文件记录一些完整的类名。 这些类名将用于通过反射创建实例。 升级逻辑尝试使用SystemClassLoader.getResourceAsStream()加载属性文件。

如果jar文件(jarA.jar)被替换为新文件,并且属性的内容发生了更改,则会发生此异常。 似乎SystemClassLoader无法正确加载属性。

该项目由java1.4编译,并在jre1.7上运行,Os是Windows。

有没有人可以解释为什么SystemClassLoader在属性存在时无法加载? 我感谢您的帮助。

通常只有在第一次需要时才从jar文件中读取类。

当JVM运行时替换jar文件时,JVM所具有的文件InputStream已经过时了。 在这种情况下,如果未更改JAR文件的内容,则可以从jar中读取类。 如果替换的jar具有与旧jar不同的内容,则obsolte InputStream将尝试读取其已知的位置。 但是,由于conent已更改,因此可能无法读取文件。

因此这个例外

类重新加载通常是通过丢弃旧的类加载器并为类的更新版本创建新的类加载器来完成的。 据我所知,无法在同一个类加载器中重新加载更改的类。

重新加载属性文件是另一个问题。 但是它不能包含在jar中,你必须监视文件的变化。 在这种情况下,您也不应该使用getResourceAsStream()。

如果要在替换jar文件后使用getResourceAsStream(String),则只需实现自己的方法ClassLoader.findResource(String)

public URL findResource(final String name) {
    // find URL (and cache it if necessary (Hashtable ?))
    // do not call super.findResource(String)
    return url; // in a jar: new URL("jar:jar-path!/" + name);
}

它将确保正确地重新加载任何资源(即使在jar中)。

(我仍然不确定,但是默认的类加载器似乎存储了与第一个找到的URL的连接,它在替换源后失效,但在负责类的类加载器中保持不变)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM