.JAR 文件在执行时是否不执行校验和检查?

Does a .JAR file not perform a checksum check when executed?

我正在测试以下内容:
- 更改 JAR 文件的内容(通过 Notepad++)
- 保存并运行它

由于 JAR 文件基本上只是 ZIP 存档,我假设在 JVM 实际上 运行s JAR 文件之前,校验和正在被验证。但事实并非如此,JAR 文件被执行并抛出异常,缺少某些东西。

例如用7zip解压时,报CRC错误。当 运行 设置它时,我预计会出现相同的行为。

我错过了什么吗?或者实际上没有执行校验和检查 before/while 运行 一个 JAR 文件?

简答:

只要你不使用旧的 Java 版本 <= 7 就错过了这个 bug 的修复,并且只要你不使用自定义 ClassLoader 每个 zip 的 CRC从 classpath.

加载 JAR 时验证 JAR 文件中的条目

长答案(以 Java 8 为例,我不知道较新的 Java 版本中有任何已知的回归错误):

Java 的 URLClassLoader(Java 8 中的默认系统 classloader)使用 class sun.net/www/protocol/jar/JarURLConnection 从 URL 读取 JAR 文件。

这个 class 使用 sun/net/www/protocol/jar/URLJarFile 这是 class 的子 class java/util/zip/ZipFile. This class calls the read method of a java/util/zip/ZipInputStream 读取 zip 条目。

ZipInputStream class 验证未压缩 Zip 条目的 CRC here and for compressed ZIP entries here。如果 zip 条目损坏(每个 Zip 条目都有一个 CRC,而不是整个 ZIP 文件),则会抛出 ZipException。


您得到一个 java.lang.NoClassDefFoundError,因为无法加载 JAR 文件。之前肯定有错误。我没有检查错误处理,但我猜 ZipException 在某个地方被捕获和记录,或者可能作为 NoClassDefFoundError 的原因添加。由于您既不共享 JAR 文件,也没有任何错误输出,因此很难验证。另一种可能性是只跳过单个损坏的 ZIP 条目并加载其他条目 - 我没有时间深入研究错误处理,如果你有兴趣看一下,我链接了所有提到的 classes 到源代码。