我有一个由多个罐子组成的项目,其中一部分是我们的,另一部分是第三方库。应用程序必须通过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
到目前为止,我已经测试了这个版本的库:
使用target_jdk = 8编译项目。罐子用自签名证书签名,但我用生产(官方)证书测试,问题仍然存在。我尝试了-verbose:class
和setInterval
,但它没有用。修改:将其移至单独的问题:Tracing JNLP class loading
最有趣的部分。如果我将这些库重新打包到我自己的jar(jar-with-dependencies)中,它们甚至可以通过JNLP加载。
可能是什么问题?
答案 0 :(得分:0)
我明白了。事情是奇妙的。事实证明,当作为常规桌面Java应用程序构建时,jar确实与JNLP构建的不同。一个自定义maven插件已经到位,重建了罐子。当它将类从JarInputStream
复制到JarOutputStream
时,它使用ZipEntry::size
来获取要传输的字节数。但事实证明,这种方法无法保证报告正确的值(严肃地说,作者?)。它适用于较旧的库,因为报告的值对他们来说是正确的,但并不总是适用于较新的库。