jMockit初始化错误:java.lang.IllegalStateException:在JDK 9上运行。

4
无法在eclipse中初始化:
java.lang.IllegalStateException:在JDK 9上运行需要-javaagent:/jmockit-1.n.jar或-Djdk.attach.allowAttachSelf

如果我添加-Djdk.attach.allowAttachSelf VM参数,就可以正常工作。

为什么需要添加这个参数?当在JDK 9上运行时,jmockit并没有说需要这样做。是的,JRE系统库指向JDK,而且jmockit jar位于外部库的顺序之上junit。

版本:JUnit 4.12,Java jdk 9.0.1,jmockit 1.37,hamcrest core 1.3
java.lang.ExceptionInInitializerError at testClass.testMethod(testClass.java:20) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207) 原因:java.lang.IllegalStateException: Running on JDK 9 requires -javaagent:/jmockit-1.n.jar or -Djdk.attach.allowAttachSelf at mockit.internal.startup.AgentLoader.attachToRunningVM(AgentLoader.java:155) at mockit.internal.startup.AgentLoader.loadAgent(AgentLoader.java:60) at mockit.internal.startup.Startup.verifyInitialization(Startup.java:137) at mockit.Invocations.(Invocations.java:26) ... 24 more

请注意,JMockit在JDK 9上是必需的(或者使用-javaagent),这在异常消息中已经说明了!这比大多数人从未阅读的文档要好得多... - Rogério
@Rogerio,哈,我总是因为阅读文档而惹麻烦... - user2706641
1个回答

5

-Djdk.attach.allowAttachSelf虚拟机参数,它可以正常工作。

为什么我需要添加这个参数?

JDK9中的这个参数用于连接到本地虚拟机本身,换句话说是自我连接。

jmockit在大多数情况下使用自我连接进行Instrumentation,这就是他们需要这样一个标志的地方。此外,在JDK8或之前,该参数将被忽略。

关于这个问题的初始讨论可以在jigsaw邮件列表中找到。


类似的讨论和解决方法在byte-buddy#295中由@Rafael提出:

ByteBuddyAgent.install()现在检测到禁止自我连接的Java 9 VM,并创建一个辅助进程以从那里连接。


6
我认为真正的原因是某个Oracle JDK工程师做了一个武断、无效且最终毫无意义的决定,即添加命令行标志作为一种防止恶意代码通过字节码检测正在运行的JVM的方式。事实上,一个库可以轻松地绕过这个标志,只需创建一个新进程,然后将其附加回原始进程即可证明该标志没有实现任何有用的功能。相反,他们应该简单地依赖已经存在的AttachPermission - Rogério
@Rogério 嗯,我同意旗帜似乎没有很有效的目的。也许 Alan(如果)可以查看此事,并提供一些关于效果方面的细节。 - Naman
已经提交了问题#544(https://github.com/jmockit/jmockit1/issues/544),要求JMockit实现类似于Byte Buddy的解决方案,以便不再需要此标志。 - Thunderforge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接