11

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)
Naman
  • 27,789
  • 26
  • 218
  • 353
Vivek Shankar
  • 770
  • 1
  • 15
  • 37
  • 6
    Where does that linked discussion say that `-Djdk.attach.allowAttachSelf=true` will not work anymore under JDK11? – Holger Jun 27 '19 at 14:54
  • 1
    You need to setup the property on VM startup, not during runtime, otherwise it is ignored. Otherwise, have a look at byte-buddy-agent which can work around the restriction. – Rafael Winterhalter Jun 28 '19 at 07:57
  • @Holger It doesn't. But how can I set the parameter during one of the test cases run which is trying to attach the agent to a JVM, IIUC, which was created by Maven. – Vivek Shankar Jun 29 '19 at 12:58
  • @RafaelWinterhalter I'm not sure I follow, how can I set the property from a test case before the VM startup? And yes, I am looking at byte-buddy-agent code and trying to do the attach from a helper process. Being the rookie that I am, haven't managed to get it working yet. – Vivek Shankar Jun 29 '19 at 13:01
  • 2
    You cannot, you need to boot up the VM with that property set, otherwise, the restriction would be pointless. byte-buddy-agent only requires you to call install to get hold of the instrumentation instance. If it's not working, let me know where you are stuck. – Rafael Winterhalter Jun 29 '19 at 18:36
  • Also an option: Start a new process that does the attach to the current VM. – Johannes Kuhn Jul 18 '20 at 11:55
  • @JohannesKuhn yeah, you're right that's how bytebuddy did it. – Vivek Shankar Aug 06 '20 at 02:59

5 Answers5

5

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.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
  • We launch a VM from within our application. I can attest that adding -Djdk.attach.allowAttachSelf=true to the VM args does allow it to attach and I can get a remote data dump. We use this to find the OS thread ids for each of our java threads so we can tell what thread is running away. – daveca Dec 16 '21 at 20:01
  • The OpenJDK issue "JDK-8180425 : Release Note: Attach API cannot be used to attach to the current VM by default" has been moved to https://bugs.openjdk.org/browse/JDK-8180425 – OndroMih Nov 28 '22 at 18:48
3

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>
Vivek Shankar
  • 770
  • 1
  • 15
  • 37
0

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>
Mansingh Kachhi
  • 87
  • 2
  • 2
  • 9
0

@SolarisNeko

use JVM args: -Djdk.attach.allowAttachSelf=true

you can resolve it.

0

In my case, I was compiling my android project with below setting while the compiler is set to Jdk11 (azul zulu). Changing the JDK to jdk1.8 fixed the issue.

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

enter image description here

PravyNandas
  • 607
  • 11
  • 12