4

jmockit cannot initialize in eclipse: java.lang.IllegalStateException: Running on JDK 9 requires -javaagent:/jmockit-1.n.jar or -Djdk.attach.allowAttachSelf

If I add the -Djdk.attach.allowAttachSelf VM argument, it works fine.

Why would I need to add that argument? jmockit doesn't say that is required when running on JDK 9. Yes, the JRE System library points to JDK, and yes the jmockit jar is above junit in the order of external libraries.

Versions: 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) Caused by: 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

Stefan Birkner
  • 24,059
  • 12
  • 57
  • 72
user2706641
  • 67
  • 1
  • 4
  • Note that JMockit *does* say it is required (well, that or using `-javaagent`) on JDK 9, in the exception message! Better than documentation, which most people never read... – Rogério Nov 28 '17 at 18:15
  • @Rogerio, ha, i always do get in trouble for reading documentation... – user2706641 Nov 29 '17 at 01:09

1 Answers1

5

-Djdk.attach.allowAttachSelf vm argument, it works fine.

Why would I need to add that argument?

The argument in JDK9 is used to attach to the local VM itself in other words for self-attach.

jmockit mostly uses a self-attach for Instrumentation and that is where they would be requiring such a flag. Also, this must argument shall be ignored on JDK8 or previous.

An initial discussion over the same could be found on jigsaw mailing list.


A similar discussion and a workaround was proposed at byte-buddy#295 by @Rafael :-

ByteBuddyAgent.install() does now detect Java 9 VMs where self-attachment is forbidden and creates a helper process to attach from there.

Naman
  • 27,789
  • 26
  • 218
  • 353
  • 6
    I would say the *real* reason is because some Oracle JDK engineer made this arbitrary, inefective, and ultimately non-sensical decision of adding a command line flag as a way to prevent malicious code from bytecode instrumenting the running JVM. The fact that a library can easily work around the flag by creating a new process which then attaches back to the original process proves the flag doesn't achieve anything useful. Instead, they should simply have relied on the `AttachPermission` which already exists. – Rogério Nov 28 '17 at 18:19
  • @Rogério Well, I second the thought that the flag seems not very effectively purposeful. Maybe Alan(if) could view this and provide some details in terms of what was the effectiveness there. – Naman Nov 28 '17 at 18:27
  • [Issue #544](https://github.com/jmockit/jmockit1/issues/544) has been filed requesting that JMockit implement a similar solution to Byte Buddy so that this flag will no longer be necessary. – Thunderforge Aug 17 '18 at 17:00