首页 文章

JNLP类加载:截断的类文件(不是maven缓存问题!)

提问于
浏览
0

我有一个由多个 jar 组成的项目,其中一部分是我们的,另一部分是第三方库 . 应用程序必须通过Java WebStart(JNLP)运行 . 在此期间我遇到两次,如果第三方库“太新”,则无法加载以下异常:

java.lang.ClassFormatError: Truncated class file
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at com.sun.jnlp.JNLPClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at com.sun.jnlp.JNLPClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at <...>.ApplicationImpl.<init>(ApplicationImpl.java:63)

类似的问题通常被称为“清除maven缓存”,但这与此无关 . 因为如果我将它作为常规的Java应用程序(而不是WebStart)运行,一切正常 . 但是,我仍然尝试过 .

我现在尝试过的JDK版本是jdk1.8.0_151,jdk1.8.0_161 .

我的测试代码如下:

try {
  LOG.debug("@@@ jackson-core");
  Class.forName("com.fasterxml.jackson.core.Versioned");
  LOG.debug("@@@ jackson-annotations");
  Class.forName("com.fasterxml.jackson.annotation.JsonAutoDetect");
  LOG.debug("@@@ jackson-databind");
  Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
} catch (ClassNotFoundException ex) {
  LOG.debug(ex);
}

到目前为止,我已经测试了这个版本的库:

  • jackson-databind / core / annotations 2 . 5 . 0(2015年1月)及以后没有加载

  • jackson-databind / core / annotations 2 . 2 . 0(2013年4月)LOADS

  • io.nats.jnats 1 . 0(2017年2月)没有加载

  • io.nats.jnats 0 . 3 . 1(2016年1月)LOADS

  • org.apache.httpcomponents.httpasyncclient 4 . 1(2015年4月)LOADS

  • org.apache.httpcomponents.httpasyncclient 4 . 1 . 1(2015年11月)及以后没有加载

该项目使用target_jdk = 8进行编译 . jar 用自签名证书签名,但我用 生产环境 (官方)证书测试,问题仍然存在 . 我已经尝试了 -XX:+TraceClassLoadinga-verbose:class 但它没有用 . 编辑:将其移至单独的问题:Tracing JNLP class loading

而最有趣的部分 . 如果我将这些库重新打包到我自己的jar(jar-with-dependencies)中,它们甚至可以通过JNLP加载 .

可能是什么问题呢?

1 回答

  • 0

    我想到了 . 事情是奇妙的 . 事实证明,当作为常规桌面Java应用程序构建时,jar确实与构建为JNLP的jar不同 . 一个自定义maven插件已经到位,重建了 jar . 当它将类从 JarInputStream 复制到 JarOutputStream 时,它使用 ZipEntry::size 来获取要传输的字节数 . 但事实证明,这种方法 is not guaranteed to report correct value (严肃地说,作者?) . 它适用于较旧的库,因为报告的值对他们来说是正确的,但并不总是适用于较新的库 .

相关问题