我有一个类加载问题。 我的应用程序捆绑为 EAR,由 WAR + 一些 EJB 和 JAR 子模块组成。 EAR 捆绑了自己版本的 Bouncy Castle 库,恰好是该库的两个模块:
NoSuchMethodError
。这是典型的堆栈跟踪摘录:
Caused by: java.lang.NoSuchMethodError: org.bouncycastle.crypto.engines.AESEngine.newInstance()Lorg/bouncycastle/crypto/MultiBlockCipher;
at org.bouncycastle.openpgp.operator.bc.BcImplProvider.createBlockCipher(Unknown Source)
at org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder$1.recoverKeyData(Unknown Source)
at org.bouncycastle.openpgp.PGPSecretKey.extractKeyData(Unknown Source)
at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source)
我已经在 JBoss 中启用了类加载器详细日志记录,这就是我所看到的:
2024-02-15 14:22:48,230 TRACE [org.jboss.modules] (Weld Thread Pool -- 1) Finding class org.bouncycastle.openpgp.PGPSecretKey from Module "deployment.myapp-ear.ear.myapp-ejb.jar" from Service Module Loader
2024-02-15 14:22:48,230 TRACE [org.jboss.modules] (Weld Thread Pool -- 1) Finding local class org.bouncycastle.openpgp.PGPSecretKey from Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:22:48,230 TRACE [org.jboss.modules] (Weld Thread Pool -- 1) Loading class org.bouncycastle.openpgp.PGPSecretKey locally from Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:27:33,162 TRACE [org.jboss.modules] (default task-35) Finding class org.bouncycastle.openpgp.operator.bc.BcImplProvider from Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:27:33,162 TRACE [org.jboss.modules] (default task-35) Finding local class org.bouncycastle.openpgp.operator.bc.BcImplProvider from Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:27:33,162 TRACE [org.jboss.modules] (default task-35) Loading class org.bouncycastle.openpgp.operator.bc.BcImplProvider locally from Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:27:33,162 TRACE [org.jboss.modules] (default task-35) Attempting to define class org.bouncycastle.openpgp.operator.bc.BcImplProvider in Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:27:33,162 TRACE [org.jboss.modules.define] (default task-35) Defined class org.bouncycastle.openpgp.operator.bc.BcImplProvider in Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:27:33,162 TRACE [org.jboss.modules] (default task-35) Finding local class org.bouncycastle.crypto.BlockCipher from Module "org.bouncycastle.bcprov" version 1.68.0.redhat-00005 from local module loader @4a11eb84 (finder: local module finder @4e858e0a (roots: /opt/rh/eap7/root/usr/share/wildfly/modules,/opt/rh/eap7/root/usr/share/wildfly/modules/system/layers/base))
2024-02-15 14:27:33,162 TRACE [org.jboss.modules] (default task-35) Loading class org.bouncycastle.crypto.BlockCipher locally from Module "org.bouncycastle.bcprov" version 1.68.0.redhat-00005 from local module loader @4a11eb84 (finder: local module finder @4e858e0a (roots: /opt/rh/eap7/root/usr/share/wildfly/modules,/opt/rh/eap7/root/usr/share/wildfly/modules/system/layers/base))
2024-02-15 14:27:33,163 TRACE [org.jboss.modules] (default task-35) Attempting to define class org.bouncycastle.crypto.BlockCipher in Module "org.bouncycastle.bcprov" version 1.68.0.redhat-00005 from local module loader @4a11eb84 (finder: local module finder @4e858e0a (roots: /opt/rh/eap7/root/usr/share/wildfly/modules,/opt/rh/eap7/root/usr/share/wildfly/modules/system/layers/base))
2024-02-15 14:27:33,163 TRACE [org.jboss.modules.define] (default task-35) Defined class org.bouncycastle.crypto.BlockCipher in Module "org.bouncycastle.bcprov" version 1.68.0.redhat-00005 from local module loader @4a11eb84 (finder: local module finder @4e858e0a (roots: /opt/rh/eap7/root/usr/share/wildfly/modules,/opt/rh/eap7/root/usr/share/wildfly/modules/system/layers/base))
2024-02-15 14:27:33,563 TRACE [org.jboss.modules] (default task-35) Finding class org.bouncycastle.crypto.engines.AESEngine from Module "deployment.myapp-ear.ear" from Service Module Loader
2024-02-15 14:27:33,563 TRACE [org.jboss.modules] (default task-35) Finding local class org.bouncycastle.crypto.engines.AESEngine from Module "org.bouncycastle.bcprov" version 1.68.0.redhat-00005 from local module loader @4a11eb84 (finder: local module finder @4e858e0a (roots: /opt/rh/eap7/root/usr/share/wildfly/modules,/opt/rh/eap7/root/usr/share/wildfly/modules/system/layers/base))
2024-02-15 14:27:33,564 TRACE [org.jboss.modules] (default task-35) Loading class org.bouncycastle.crypto.engines.AESEngine locally from Module "org.bouncycastle.bcprov" version 1.68.0.redhat-00005 from local module loader @4a11eb84 (finder: local module finder @4e858e0a (roots: /opt/rh/eap7/root/usr/share/wildfly/modules,/opt/rh/eap7/root/usr/share/wildfly/modules/system/layers/base))
2024-02-15 14:27:33,564 TRACE [org.jboss.modules] (default task-35) Attempting to define class org.bouncycastle.crypto.engines.AESEngine in Module "org.bouncycastle.bcprov" version 1.68.0.redhat-00005 from local module loader @4a11eb84 (finder: local module finder @4e858e0a (roots: /opt/rh/eap7/root/usr/share/wildfly/modules,/opt/rh/eap7/root/usr/share/wildfly/modules/system/layers/base))
所以,正如你所看到的:bcpg 模块中的
PGPSecretKey
是从我自己的 Bouncy Castle 版本 (1.77) 加载的,捆绑在 EAR 中bcprov 模块中的
BcImplProvider
仍然从我自己的 Bouncy Castle 版本 (1.77) 加载,捆绑在 EAR 中bcprov 模块中的
BlockCipher
和
AESEngine
是从 JBoss 版本的 Bouncy Castle (1.68) 加载的
请注意:
org.bouncycastle.bcprov
和
org.bouncycastle.bcpg
放入
jboss-deployment-structure.xml
中排除的依赖项中,但没有成功;但我不希望它被需要,因为 Bouncy Castle 没有被列在隐式模块依赖项中,并且似乎是一个私有模块
use-physical-code-source
设置为
true
,再次在
jboss-deployment-structure.xml
中,但没有运气
整个 Bouncy Castle 模块添加排除项,而不仅仅是我正在使用的 Bouncy Castle 子模块(org.bouncycastle.bcprov
和
org.bouncycastle.bcpg
):所以在
META-INF/jboss-deployment-structure.xml
:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.3">
<ear-exclusions-cascaded-to-subdeployments>true</ear-exclusions-cascaded-to-subdeployments>
<deployment>
<exclusions>
<module name="org.bouncycastle"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
将 <ear-exclusions-cascaded-to-subdeployments>
设置为
true
我还确保排除适用于所有子模块。我想这可能是因为在我们的 JBoss EAP 安装中,Bouncy Castle 模块
作为一个整体似乎可用于所有已部署的应用程序。