diff --git a/boot/pom.xml b/boot/pom.xml
index 12c9a241a..15423fcd3 100644
--- a/boot/pom.xml
+++ b/boot/pom.xml
@@ -16,10 +16,6 @@
com.alibaba.middleware
cli
-
- com.github.oshi
- oshi-core
-
ch.qos.logback
diff --git a/boot/src/main/java/com/taobao/arthas/boot/ExecutingCommand.java b/boot/src/main/java/com/taobao/arthas/boot/ExecutingCommand.java
new file mode 100644
index 000000000..24cfc111a
--- /dev/null
+++ b/boot/src/main/java/com/taobao/arthas/boot/ExecutingCommand.java
@@ -0,0 +1,111 @@
+package com.taobao.arthas.boot;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A class for executing on the command line and returning the result of
+ * execution.
+ *
+ * @author alessandro[at]perucchi[dot]org
+ */
+public class ExecutingCommand {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ExecutingCommand.class);
+
+ private ExecutingCommand() {
+ }
+
+ /**
+ * Executes a command on the native command line and returns the result.
+ *
+ * @param cmdToRun
+ * Command to run
+ * @return A list of Strings representing the result of the command, or empty
+ * string if the command failed
+ */
+ public static List runNative(String cmdToRun) {
+ String[] cmd = cmdToRun.split(" ");
+ return runNative(cmd);
+ }
+
+ /**
+ * Executes a command on the native command line and returns the result line by
+ * line.
+ *
+ * @param cmdToRunWithArgs
+ * Command to run and args, in an array
+ * @return A list of Strings representing the result of the command, or empty
+ * string if the command failed
+ */
+ public static List runNative(String[] cmdToRunWithArgs) {
+ Process p = null;
+ try {
+ p = Runtime.getRuntime().exec(cmdToRunWithArgs);
+ } catch (SecurityException e) {
+ LOG.trace("Couldn't run command {}: {}", Arrays.toString(cmdToRunWithArgs), e);
+ return new ArrayList(0);
+ } catch (IOException e) {
+ LOG.trace("Couldn't run command {}: {}", Arrays.toString(cmdToRunWithArgs), e);
+ return new ArrayList(0);
+ }
+
+ ArrayList sa = new ArrayList();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ try {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ sa.add(line);
+ }
+ p.waitFor();
+ } catch (IOException e) {
+ LOG.trace("Problem reading output from {}: {}", Arrays.toString(cmdToRunWithArgs), e);
+ return new ArrayList(0);
+ } catch (InterruptedException ie) {
+ LOG.trace("Interrupted while reading output from {}: {}", Arrays.toString(cmdToRunWithArgs), ie);
+ Thread.currentThread().interrupt();
+ } finally {
+ IOUtils.close(reader);
+ }
+ return sa;
+ }
+
+ /**
+ * Return first line of response for selected command.
+ *
+ * @param cmd2launch
+ * String command to be launched
+ * @return String or empty string if command failed
+ */
+ public static String getFirstAnswer(String cmd2launch) {
+ return getAnswerAt(cmd2launch, 0);
+ }
+
+ /**
+ * Return response on selected line index (0-based) after running selected
+ * command.
+ *
+ * @param cmd2launch
+ * String command to be launched
+ * @param answerIdx
+ * int index of line in response of the command
+ * @return String whole line in response or empty string if invalid index or
+ * running of command fails
+ */
+ public static String getAnswerAt(String cmd2launch, int answerIdx) {
+ List sa = ExecutingCommand.runNative(cmd2launch);
+
+ if (answerIdx >= 0 && answerIdx < sa.size()) {
+ return sa.get(answerIdx);
+ }
+ return "";
+ }
+
+}
diff --git a/boot/src/main/java/com/taobao/arthas/boot/OSUtils.java b/boot/src/main/java/com/taobao/arthas/boot/OSUtils.java
new file mode 100644
index 000000000..36581f819
--- /dev/null
+++ b/boot/src/main/java/com/taobao/arthas/boot/OSUtils.java
@@ -0,0 +1,38 @@
+package com.taobao.arthas.boot;
+
+/**
+ *
+ * @author hengyunabc 2018-11-08
+ *
+ */
+public class OSUtils {
+
+ static PlatformEnum platform;
+ static {
+ String osName = System.getProperty("os.name");
+ if (osName.startsWith("Linux")) {
+ platform = PlatformEnum.LINUX;
+ } else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
+ platform = PlatformEnum.MACOSX;
+ } else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
+ platform = PlatformEnum.MACOSX;
+ } else if (osName.startsWith("Windows")) {
+ platform = PlatformEnum.WINDOWS;
+ } else {
+ platform = PlatformEnum.UNKNOWN;
+ }
+ }
+
+ public static boolean isWindows() {
+ return platform == PlatformEnum.WINDOWS;
+ }
+
+ public static boolean isLinux() {
+ return platform == PlatformEnum.LINUX;
+ }
+
+ public static boolean isMac() {
+ return platform == PlatformEnum.MACOSX;
+ }
+
+}
diff --git a/boot/src/main/java/com/taobao/arthas/boot/PlatformEnum.java b/boot/src/main/java/com/taobao/arthas/boot/PlatformEnum.java
new file mode 100644
index 000000000..966023f76
--- /dev/null
+++ b/boot/src/main/java/com/taobao/arthas/boot/PlatformEnum.java
@@ -0,0 +1,22 @@
+package com.taobao.arthas.boot;
+
+/**
+ * Enum of supported operating systems.
+ *
+ */
+public enum PlatformEnum {
+ /**
+ * Microsoft Windows
+ */
+ WINDOWS,
+ /**
+ * A flavor of Linux
+ */
+ LINUX,
+ /**
+ * macOS (OS X)
+ */
+ MACOSX,
+
+ UNKNOWN;
+}
\ No newline at end of file
diff --git a/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java b/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java
index 9a81ec1da..96301756e 100644
--- a/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java
+++ b/boot/src/main/java/com/taobao/arthas/boot/ProcessUtils.java
@@ -5,6 +5,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -15,10 +16,6 @@ import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import oshi.SystemInfo;
-import oshi.software.os.OSProcess;
-import oshi.software.os.OperatingSystem;
-
/**
*
* @author hengyunabc 2018-11-06
@@ -26,23 +23,41 @@ import oshi.software.os.OperatingSystem;
*/
public class ProcessUtils {
private static final Logger logger = LoggerFactory.getLogger(ProcessUtils.class);
+
+ private static String PID = "-1";
+
+ static {
+ // https://stackoverflow.com/a/7690178
+ String jvmName = ManagementFactory.getRuntimeMXBean().getName();
+ int index = jvmName.indexOf('@');
+
+ if (index > 0) {
+ try {
+ PID = Long.toString(Long.parseLong(jvmName.substring(0, index)));
+ } catch (Throwable e) {
+ // ignore
+ }
+ }
+ }
+
+ public static String getPid() {
+ return PID;
+ }
+
public static int select(boolean v) {
Map processMap = listProcessByJps(v);
- if(processMap.isEmpty()) {
- processMap = listProcessByOshi();
- }
- if(processMap.isEmpty()) {
- System.out.println("Can not find java process.");
+ if (processMap.isEmpty()) {
+ logger.info("Can not find java process.");
return -1;
}
- //print list
+ // print list
int count = 1;
- for(String process : processMap.values()) {
- if(count == 1) {
+ for (String process : processMap.values()) {
+ if (count == 1) {
System.out.println("* [" + count + "]: " + process);
- }else {
+ } else {
System.out.println(" [" + count + "]: " + process);
}
count++;
@@ -50,20 +65,20 @@ public class ProcessUtils {
// read choice
String line = new Scanner(System.in).nextLine();
- if(line.trim().isEmpty()) {
+ if (line.trim().isEmpty()) {
// get the first process id
return processMap.keySet().iterator().next();
}
int choice = new Scanner(line).nextInt();
- if(choice <= 0 || choice > processMap.size()) {
+ if (choice <= 0 || choice > processMap.size()) {
return -1;
}
Iterator idIter = processMap.keySet().iterator();
- for(int i = 1; i <= choice; ++i) {
- if(i == choice) {
+ for (int i = 1; i <= choice; ++i) {
+ if (i == choice) {
return idIter.next();
}
idIter.next();
@@ -72,28 +87,11 @@ public class ProcessUtils {
return -1;
}
- private static Map listProcessByOshi() {
- SystemInfo info = new SystemInfo();
- OperatingSystem operatingSystem = info.getOperatingSystem();
- Map result = new LinkedHashMap();
- OSProcess[] processes = operatingSystem.getProcesses(-1, null);
- for (OSProcess p : processes) {
- System.err.println(p);
- System.err.println(p.getPath());
- String path = p.getPath();
- String name = new File(path).getName();
- if (name.equals("java") || name.equals("java.exe")) {
- result.put(p.getProcessID(), p.getProcessID() + " " + path);
- }
- }
- return result;
- }
-
private static Map listProcessByJps(boolean v) {
Map result = new LinkedHashMap();
File jps = findJps();
- if(jps == null) {
+ if (jps == null) {
return result;
}
@@ -111,8 +109,12 @@ public class ProcessUtils {
// read the output from the command
String line = null;
+ int currentPid = Integer.parseInt(ProcessUtils.getPid());
while ((line = stdInput.readLine()) != null) {
int pid = new Scanner(line).nextInt();
+ if (pid == currentPid) {
+ continue;
+ }
result.put(pid, line);
}
} catch (Throwable e) {
@@ -125,51 +127,46 @@ public class ProcessUtils {
public static void startArthasCore(int targetPid, List attachArgs) {
// find java/java.exe, then try to find tools.jar
- SystemInfo info = new SystemInfo();
- OperatingSystem operatingSystem = info.getOperatingSystem();
- OSProcess processe = operatingSystem.getProcess(targetPid);
- if(processe == null) {
- throw new IllegalArgumentException("process do not exist! pid: " + targetPid);
- }
+ String javaHome = System.getProperty("java.home");
- String path = processe.getPath();
+ float javaVersion = Float.parseFloat(System.getProperty("java.specification.version"));
- // some app like eclipse process path is not java/java.exe
- if(!path.endsWith("java") && path.endsWith("java.exe")) {
- OSProcess myselfProcess = operatingSystem.getProcess(operatingSystem.getProcessId());
- path = myselfProcess.getPath();
- logger.warn("The target process is not an normal java process. try to start by using current java.");
+ // find java/java.exe
+ File javaPath = findJava();
+ if (javaPath == null) {
+ throw new IllegalArgumentException(
+ "Can not find java/java.exe executable file under java home: " + javaHome);
}
- File javaBinDir = new File(path).getParentFile();
-
- // current/jre/bin/java
- // current/bin/java
- // current/lib/tools.jar
- // after jdk9, there is no tools.jar
- File toolsJar = new File(javaBinDir , "../lib/tools.jar");
- if(!toolsJar.exists()) {
+ File toolsJar = new File(javaHome, "../lib/tools.jar");
+ if (!toolsJar.exists()) {
// maybe jre
- toolsJar = new File(javaBinDir , "../../lib/tools.jar");
+ toolsJar = new File(javaHome, "../../lib/tools.jar");
+ }
+
+ if (javaVersion < 9.0f) {
+ if (!toolsJar.exists()) {
+ throw new IllegalArgumentException("Can not find tools.jar under java home: " + javaHome);
+ }
}
List command = new ArrayList();
- command.add(path);
+ command.add(javaPath.getAbsolutePath());
- if(toolsJar.exists()) {
+ if (toolsJar.exists()) {
command.add("-Xbootclasspath/a:" + toolsJar.getAbsolutePath());
}
command.addAll(attachArgs);
-// "${JAVA_HOME}"/bin/java \
-// ${opts} \
-// -jar "${arthas_lib_dir}/arthas-core.jar" \
-// -pid ${TARGET_PID} \
-// -target-ip ${TARGET_IP} \
-// -telnet-port ${TELNET_PORT} \
-// -http-port ${HTTP_PORT} \
-// -core "${arthas_lib_dir}/arthas-core.jar" \
-// -agent "${arthas_lib_dir}/arthas-agent.jar"
+ // "${JAVA_HOME}"/bin/java \
+ // ${opts} \
+ // -jar "${arthas_lib_dir}/arthas-core.jar" \
+ // -pid ${TARGET_PID} \
+ // -target-ip ${TARGET_IP} \
+ // -telnet-port ${TELNET_PORT} \
+ // -http-port ${HTTP_PORT} \
+ // -core "${arthas_lib_dir}/arthas-core.jar" \
+ // -agent "${arthas_lib_dir}/arthas-agent.jar"
ProcessBuilder pb = new ProcessBuilder(command);
try {
@@ -205,7 +202,7 @@ public class ProcessUtils {
redirectStderr.join();
int exitValue = proc.exitValue();
- if(exitValue != 0) {
+ if (exitValue != 0) {
logger.error("attach fail, targetPid: " + targetPid);
System.exit(1);
}
@@ -215,6 +212,21 @@ public class ProcessUtils {
}
+ private static File findJava() {
+ String javaHome = System.getProperty("java.home");
+ String[] paths = { "bin/java", "bin/java.exe", "../bin/java", "../bin/java.exe" };
+
+ for (String path : paths) {
+ File jpsFile = new File(javaHome, path);
+ if (jpsFile.exists()) {
+ return jpsFile;
+ }
+ }
+
+ logger.debug("can not find java under current java home: " + javaHome);
+ return null;
+ }
+
private static File findJps() {
String javaHome = System.getProperty("java.home");
String[] paths = { "bin/jps", "bin/jps.exe", "../bin/jps", "../bin/jps.exe" };
@@ -226,6 +238,7 @@ public class ProcessUtils {
}
}
+ logger.debug("can not find jps under current java home: " + javaHome);
return null;
}
diff --git a/boot/src/main/java/com/taobao/arthas/boot/SocketUtils.java b/boot/src/main/java/com/taobao/arthas/boot/SocketUtils.java
index 0703a5c92..4b95d8cb7 100644
--- a/boot/src/main/java/com/taobao/arthas/boot/SocketUtils.java
+++ b/boot/src/main/java/com/taobao/arthas/boot/SocketUtils.java
@@ -6,9 +6,6 @@ import java.util.List;
import javax.net.ServerSocketFactory;
-import oshi.PlatformEnum;
-import oshi.SystemInfo;
-import oshi.util.ExecutingCommand;
/**
*
@@ -19,8 +16,7 @@ public class SocketUtils {
public static int findTcpListenProcess(int port) {
try {
- PlatformEnum platformEnum = SystemInfo.getCurrentPlatformEnum();
- if (PlatformEnum.WINDOWS.equals(platformEnum)) {
+ if (OSUtils.isWindows()) {
String[] command = { "netstat", "-ano", "-p", "TCP" };
List lines = ExecutingCommand.runNative(command);
for (String line : lines) {
@@ -36,7 +32,7 @@ public class SocketUtils {
}
}
- if (PlatformEnum.MACOSX.equals(platformEnum) || PlatformEnum.LINUX.equals(platformEnum)) {
+ if (OSUtils.isLinux() || OSUtils.isMac()) {
String pid = ExecutingCommand.getFirstAnswer("lsof -t -s TCP:LISTEN -i TCP:" + port);
if (!pid.trim().isEmpty()) {
return Integer.parseInt(pid);
diff --git a/pom.xml b/pom.xml
index cb5186af2..3dcae6f6c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -172,11 +172,6 @@
2.14.6
-
- com.github.oshi
- oshi-core
- 3.9.1
-