Mockito、Java 9和Java.lang.ClassNotFoundException:sun.reflect.ReflectionFactory
我的项目是一个使用Mockito测试库的Wildfly 13应用程序。应用程序未使用Java 9模块结构。只要服务器在Java 8上运行,测试就可以正常工作,但一旦我们升级到Java 9,测试就会失败,出现以下异常:Mockito、Java 9和Java.lang.ClassNotFoundException:sun.reflect.ReflectionFactory,java,mockito,wildfly,java-9,Java,Mockito,Wildfly,Java 9,我的项目是一个使用Mockito测试库的Wildfly 13应用程序。应用程序未使用Java 9模块结构。只要服务器在Java 8上运行,测试就可以正常工作,但一旦我们升级到Java 9,测试就会失败,出现以下异常: org.objenesis.ObjenesisException: java.lang.ClassNotFoundException: sun.reflect.ReflectionFactory from [Module "test.war" from Service Module
org.objenesis.ObjenesisException: java.lang.ClassNotFoundException: sun.reflect.ReflectionFactory from [Module "test.war" from Service Module Loader]
at test.war//org.objenesis.instantiator.sun.SunReflectionFactoryHelper.getReflectionFactoryClass(SunReflectionFactoryHelper.java:63)
at test.war//org.objenesis.instantiator.sun.SunReflectionFactoryHelper.newConstructorForSerialization(SunReflectionFactoryHelper.java:37)
at test.war//org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.<init>(SunReflectionFactoryInstantiator.java:41)
at test.war//org.objenesis.strategy.StdInstantiatorStrategy.newInstantiatorOf(StdInstantiatorStrategy.java:68)
at test.war//org.objenesis.ObjenesisBase.getInstantiatorOf(ObjenesisBase.java:94)
at test.war//org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
at test.war//org.mockito.internal.creation.instance.ObjenesisInstantiator.newInstance(ObjenesisInstantiator.java:19)
at test.war//org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMock(SubclassByteBuddyMockMaker.java:47)
at test.war//org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.createMock(ByteBuddyMockMaker.java:25)
at test.war//org.mockito.internal.util.MockUtil.createMock(MockUtil.java:35)
at test.war//org.mockito.internal.MockitoCore.mock(MockitoCore.java:68)
at test.war//org.mockito.Mockito.mock(Mockito.java:1895)
at test.war//org.mockito.Mockito.mock(Mockito.java:1804)
at test.war//application code...
我认为问题可能在于您使用的是Java 9的早期版本。在一些早期的access版本中,访问
sun.reflect
库时出现问题。尝试将您的Java 9版本更新为类似(尽管不同)问题中建议的9-ea+115版本之后的更高版本。经过进一步挖掘,我找到了指向我的解决方案。这篇文章有一个标题为“访问JDK类”的部分,其中指出默认情况下并非所有类都可用于部署,您需要将它们添加到jboss-deployment-structure.xml
以使它们可用
就我而言:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
<deployment>
<dependencies>
<system export="true">
<paths>
<path name="sun/reflect"/>
</paths>
</system>
</dependencies>
</deployment>
</jboss-deployment-structure>
此解决方案适用于
- Wildfly 13,在Java 10.0.2上运行(9.0.4也起作用)
- 用Java8编译的应用程序
- Mockito 1.10.19(我尝试了2.20.0,但出现了新的错误)
从Java 11、WildFly 14+和Mockito 2.23.0+开始,在WAR中添加jdk。不受支持的模块依赖性解决了问题。您可以通过两种方式执行此操作:
A.META-INF/MANIFEST.MF
将以下行添加到WAR存档的META\u INF/MANIFEST.MF
:
Dependencies: jdk.unsupported
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="jdk.unsupported" />
</dependencies>
</deployment>
</jboss-deployment-structure>
请注意,该文件已被删除
以下是使用包覆面提取/Arquillian的典型方法:
@Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class, "my-app.war")
.addPackages(true, Mockito.class.getPackage(), Objenesis.class.getPackage(), ByteBuddy.class.getPackage())
.addAsManifestResource(new StringAsset("Dependencies: jdk.unsupported\n" /* required by Mockito */), "MANIFEST.MF");
}
B.WEB-INF/jboss部署结构.xml
将以下内容添加到您的WAR归档文件中:
Dependencies: jdk.unsupported
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="jdk.unsupported" />
</dependencies>
</deployment>
</jboss-deployment-structure>
您使用的是Mockito的最新版本吗?@Nicolai是。尝试了最新、旧版本,没有更改。是否可以使用--show module resolution运行,以查看jdk.unsupported是否已解决?如果没有,则Wildfly必须使用一些限制可观察性的选项运行。@AlanBateman我已将使用建议标志运行Wildfly的结果添加到问题中。显示模块解析输出显示jdk.unsupported已解析,这意味着它导出的sun.reflect API可用。这一定是类加载器委托的问题-您添加的答案似乎是确认这一点。我在编译和运行时都使用了最新版本的OpenJDK 9和10(我用这些信息更新了我的问题)。感谢您指出收缩包装/Arquillian方法,通过问题解决。解决方案A“EarContent/META-INF/MANIFEST.MF”适用于我JDK11+WIldFly20,jboss序列化库调用sun/reflect作为JEE ear。