--quiet
* @param pVm the virtual machine
+ * @param pHandler platform-specific way to invoke operations on VM
* @return the exit code (0: agent is attached, 1: agent is not attached.)
*/
@Override
@SuppressWarnings("PMD.SystemPrintln")
- int execute(OptionsAndArgs pOptions, Object pVm, VirtualMachineHandler pHandler)
+ int execute(OptionsAndArgs pOptions, Object pVm, VirtualMachineHandlerOperations pHandler)
throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
- String agentUrl = checkAgentUrl(pVm);
+ String agentUrl = checkAgentUrl(pVm, pHandler);
boolean quiet = pOptions.isQuiet();
if (agentUrl != null) {
if (!quiet) {
- System.out.println("Jolokia started for " + getProcessDescription(pOptions,pHandler));
+ System.out.println("Jolokia started for " + getProcessDescription(pHandler, pOptions));
System.out.println(agentUrl);
}
return 0;
} else {
if (!quiet) {
- System.out.println("No Jolokia agent attached to " + getProcessDescription(pOptions,pHandler));
+ System.out.println("No Jolokia agent attached to " + getProcessDescription(pHandler, pOptions));
}
return 1;
}
diff --git a/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/StopCommand.java b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/StopCommand.java
index 7c464f14e..aa2b5452b 100644
--- a/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/StopCommand.java
+++ b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/StopCommand.java
@@ -19,7 +19,7 @@
import java.lang.reflect.InvocationTargetException;
import org.jolokia.jvmagent.client.util.OptionsAndArgs;
-import org.jolokia.jvmagent.client.util.VirtualMachineHandler;
+import org.jolokia.jvmagent.client.util.VirtualMachineHandlerOperations;
/**
* Stop a Jolokia Agent, but only if it is already running (started with 'start').
@@ -40,18 +40,18 @@ String getName() {
/** {@inheritDoc} */
@Override
@SuppressWarnings("PMD.SystemPrintln")
- int execute(OptionsAndArgs pOpts, Object pVm, VirtualMachineHandler pHandler) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
- String agentUrl = checkAgentUrl(pVm);
+ int execute(OptionsAndArgs pOpts, Object pVm, VirtualMachineHandlerOperations pHandler) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ String agentUrl = checkAgentUrl(pVm, pHandler);
boolean quiet = pOpts.isQuiet();
if (agentUrl != null) {
- loadAgent(pVm,pOpts,"mode=stop");
+ loadAgent(pVm, pHandler, pOpts, "mode=stop");
if (!quiet) {
- System.out.println("Stopped Jolokia for " + getProcessDescription(pOpts,pHandler));
+ System.out.println("Stopped Jolokia for " + getProcessDescription(pHandler, pOpts));
}
return 0;
} else {
if (!quiet) {
- System.out.println("Jolokia is not attached to " + getProcessDescription(pOpts,pHandler));
+ System.out.println("Jolokia is not attached to " + getProcessDescription(pHandler, pOpts));
}
return 1;
}
diff --git a/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/ToggleCommand.java b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/ToggleCommand.java
index ddade0817..422628771 100644
--- a/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/ToggleCommand.java
+++ b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/ToggleCommand.java
@@ -19,7 +19,7 @@
import java.lang.reflect.InvocationTargetException;
import org.jolokia.jvmagent.client.util.OptionsAndArgs;
-import org.jolokia.jvmagent.client.util.VirtualMachineHandler;
+import org.jolokia.jvmagent.client.util.VirtualMachineHandlerOperations;
/**
* Toggle between "start" and "stop" depending on the existance of the system
@@ -42,8 +42,8 @@ String getName() {
/** {@inheritDoc} */
@Override
- int execute(OptionsAndArgs pOpts, Object pVm, VirtualMachineHandler pHandler) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
- return checkAgentUrl(pVm) == null ?
+ int execute(OptionsAndArgs pOpts, Object pVm, VirtualMachineHandlerOperations pHandler) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ return checkAgentUrl(pVm, pHandler) == null ?
startCommand.execute(pOpts, pVm, pHandler) :
stopCommand.execute(pOpts,pVm,pHandler);
}
diff --git a/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/VersionCommand.java b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/VersionCommand.java
index 768b43591..7183418b4 100644
--- a/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/VersionCommand.java
+++ b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/command/VersionCommand.java
@@ -20,7 +20,7 @@
import org.jolokia.Version;
import org.jolokia.jvmagent.client.util.OptionsAndArgs;
-import org.jolokia.jvmagent.client.util.VirtualMachineHandler;
+import org.jolokia.jvmagent.client.util.VirtualMachineHandlerOperations;
/**
* Print out the version of the agent
@@ -36,7 +36,7 @@ String getName() {
@Override
@SuppressWarnings({"PMD.SystemPrintln"})
- int execute(OptionsAndArgs pOpts, Object pVm, VirtualMachineHandler pHandler) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
+ int execute(OptionsAndArgs pOpts, Object pVm, VirtualMachineHandlerOperations pHandler) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
StringBuilder version = new StringBuilder("Jolokia JVM Agent ").append(Version.getAgentVersion());
if (pOpts.isVerbose()) {
version.append(" (Protocol: ").append(Version.getProtocolVersion()).append(")");
diff --git a/agent/jvm/src/main/java/org/jolokia/jvmagent/client/util/DirectVirtualMachineHandler.java b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/util/DirectVirtualMachineHandler.java
new file mode 100644
index 000000000..db4e4e64d
--- /dev/null
+++ b/agent/jvm/src/main/java/org/jolokia/jvmagent/client/util/DirectVirtualMachineHandler.java
@@ -0,0 +1,115 @@
+package org.jolokia.jvmagent.client.util;
+
+/*
+ * Copyright 2009-2021 Roland Huss
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.sun.tools.attach.AgentInitializationException;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.VirtualMachineDescriptor;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+/**
+ * A handler for dealing with VirtualMachine
directly accessing {@link com.sun.tools.attach.VirtualMachine}
+ * class available in {@code jdk.attach} module.
+ *
+ * @author ggrzybek
+ * @since 12.08.11
+ */
+class DirectVirtualMachineHandler implements VirtualMachineHandlerOperations {
+
+ private final OptionsAndArgs options;
+
+ DirectVirtualMachineHandler(OptionsAndArgs options) {
+ this.options = options;
+ }
+
+ @Override
+ public Object attachVirtualMachine() throws ProcessingException {
+ if (options.getPid() == null && options.getProcessPattern() == null) {
+ return null;
+ }
+ String pid = PlatformUtils.getProcessId(this, options);
+ try {
+ return VirtualMachine.attach(pid);
+ } catch (AttachNotSupportedException e) {
+ throw new ProcessingException(getPidErrorMesssage(pid, "AttachNotSupportedException"), e, options);
+ } catch (IOException e) {
+ throw new ProcessingException(getPidErrorMesssage(pid, "InvocationTarget"), e, options);
+ } catch (IllegalArgumentException e) {
+ throw new ProcessingException("Illegal Argument", e, options);
+ }
+ }
+
+ private String getPidErrorMesssage(String pid, String label) {
+ return pid != null ?
+ String.format("Cannot attach to process-ID %s (%s %s).\nSee --help for possible reasons.",
+ pid, label, VirtualMachine.class.getName()) :
+ String.format("%s %s",label, VirtualMachine.class.getName());
+ }
+
+ @Override
+ public void detachAgent(Object pVm) throws ProcessingException {
+ try {
+ ((VirtualMachine) pVm).detach();
+ } catch (IOException e) {
+ throw new ProcessingException("Error while detaching", e, options);
+ }
+ }
+
+ @Override
+ public ListVirtualMachine
without directly referencing internally
- * the class type. All lookup is done via reflection.
+ * the class type. All lookup is done via reflection. (Name not changed for compatibility reasons).
*
* @author roland
* @since 12.08.11
*/
-public class VirtualMachineHandler {
+class VirtualMachineHandler implements VirtualMachineHandlerOperations {
- private OptionsAndArgs options;
+ private final OptionsAndArgs options;
/**
* Constructor with options
@@ -42,7 +40,7 @@ public class VirtualMachineHandler {
* @param pOptions options for getting e.g. the process id to attach to
*
*/
- public VirtualMachineHandler(OptionsAndArgs pOptions) {
+ VirtualMachineHandler(OptionsAndArgs pOptions) {
options = pOptions;
}
@@ -56,15 +54,16 @@ public VirtualMachineHandler(OptionsAndArgs pOptions) {
*
* @return the create virtual machine of null
if none could be created
*/
- public Object attachVirtualMachine() {
+ @Override
+ public Object attachVirtualMachine() throws ProcessingException {
if (options.getPid() == null && options.getProcessPattern() == null) {
return null;
}
- Class vmClass = lookupVirtualMachineClass();
+ Class> vmClass = lookupVirtualMachineClass();
String pid = null;
try {
Method method = vmClass.getMethod("attach",String.class);
- pid = getProcessId(options);
+ pid = PlatformUtils.getProcessId(this, options);
return method.invoke(null, pid);
} catch (NoSuchMethodException e) {
throw new ProcessingException("Internal: No method 'attach' found on " + vmClass,e,options);
@@ -77,7 +76,7 @@ public Object attachVirtualMachine() {
}
}
- private String getPidErrorMesssage(String pid, String label, Class vmClass) {
+ private String getPidErrorMesssage(String pid, String label, Class> vmClass) {
return pid != null ?
String.format("Cannot attach to process-ID %s (%s %s).\nSee --help for possible reasons.",
pid, label, vmClass.getName()) :
@@ -89,10 +88,11 @@ private String getPidErrorMesssage(String pid, String label, Class vmClass) {
*
* @param pVm the virtual machine to detach from
*/
+ @Override
public void detachAgent(Object pVm) {
try {
if (pVm != null) {
- Class clazz = pVm.getClass();
+ Class> clazz = pVm.getClass();
Method method = clazz.getMethod("detach");
method.setAccessible(true); // on J9 you get IllegalAccessException otherwise.
method.invoke(pVm);
@@ -109,23 +109,30 @@ public void detachAgent(Object pVm) {
/**
* Return a list of all Java processes
* @return list of java processes
- * @throws NoSuchMethodException reflection error
- * @throws InvocationTargetException reflection error
- * @throws IllegalAccessException reflection error
+ * @throws ProcessingException reflection error
*/
- public ListA contract for dealing with VirtualMachine
on any JDK where
+ * Attach API is supported.
The virtual machine is passed as {@link Object} and dealt with differently in chosen implementation of the + * contract.
+ * + * @author ggrzybek + * @since 24.06.2021 + */ +public interface VirtualMachineHandlerOperations { + + /** + * Lookup and create a {@code com.sun.tools.attach.VirtualMachine} + * + * @return the create virtual machine ofnull
if none could be created
+ * @throws ProcessingException for any problem related to VM attaching. Specific to particular implementation.
+ */
+ Object attachVirtualMachine() throws ProcessingException;
+
+ /**
+ * Detach from the virtual machine
+ *
+ * @param pVm the virtual machine to detach from
+ * @throws ProcessingException for any problem related to VM detaching. Specific to particular implementation.
+ */
+ void detachAgent(Object pVm) throws ProcessingException;
+
+ /**
+ * Return a list of all Java processes
+ * @return list of java processes
+ */
+ List