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

时间:2018-04-02 13:24:50

标签: java jackson classloader java-web-start jnlp

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

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);
}

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

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

我的测试代码如下:

-XX:+TraceClassLoadinga

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

  • 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编译项目。罐子用自签名证书签名,但我用生产(官方)证书测试,问题仍然存在。我尝试了-verbose:classsetInterval,但它没有用。修改:将其移至单独的问题:Tracing JNLP class loading

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

可能是什么问题?

1 个答案:

答案 0 :(得分:0)

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