VirtualMachine.attach(pid) fails with java.io.IOException: Can not attach to current VM

Viewed 12307

After going through this discussion, I'm led to believe the option to attach to the same VM, by default has been disabled in OpenJDK11.

I'm trying to upgrade a java agent to OpenJDK11, during the test cases when VirtualMachine.attach(pid) is called I see it failing with below error. What is the correct way to deal with this situation?

Complete stack trace:

java.io.IOException: Can not attach to current VM

at jdk.attach/sun.tools.attach.HotSpotVirtualMachine.<init>(HotSpotVirtualMachine.java:75)
at jdk.attach/sun.tools.attach.VirtualMachineImpl.<init>(VirtualMachineImpl.java:48)
at jdk.attach/sun.tools.attach.AttachProviderImpl.attachVirtualMachine(AttachProviderImpl.java:69)
at jdk.attach/com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:207)
at org.kantega.notsoserial.WithAgentIT.attachAgent(WithAgentIT.java:76)
at org.kantega.notsoserial.WithAgentIT.attackShouldBePreventedWithAgent(WithAgentIT.java:47)
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:566)
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.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
3 Answers

See JDK-8180425 : Release Note: Attach API cannot be used to attach to the current VM by default:

The implementation of Attach API has changed in JDK 9 to disallow attaching to the current VM by default. This change should have no impact on tools that use the Attach API to attach to a running VM. It may impact libraries that mis-use this API as a way to get at the java.lang.instrument API. The system property jdk.attach.allowAttachSelf may be set on the command line to mitigate any compatibility with this change.

I'm not sure if this would help everyone, but in my case, it was a test case that tested whether the agent attaches to the JDK correctly(it won't be a self attach when the agent actually attaches to a JDK, i.e., actual runtime not a testcase).

Based on the suggestion by @Holger, in the comments, I modified my maven-failsafe-plugin to allow self attach.

        <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.22.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                    <configuration>
                        <argLine>-Djdk.attach.allowAttachSelf=true</argLine>
                        <forkMode>once</forkMode>
                    </configuration>
                </execution>
            </executions>
        </plugin>

This worked for me by adding javaagent in maven-surefire-plugin

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven-surefire-plugin.version}</version>
        <configuration>
          <!-- Centralize test reports in parent project -->
          <reportsDirectory>${basedir}/../target/surefire-reports</reportsDirectory>
          <!-- Sets the VM argument line used for Jacoco when unit tests are run. -->
          <argLine>
             -javaagent:${settings.localRepository}/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar ${surefireArgLine}
          </argLine>
        </configuration> 
</plugin>
Related