diff --git a/vjmxcli/pom.xml b/vjmxcli/pom.xml
index efeca08a..d3475c6e 100644
--- a/vjmxcli/pom.xml
+++ b/vjmxcli/pom.xml
@@ -19,13 +19,13 @@
-
+
@@ -129,6 +129,31 @@
+
+
+
+ jdk9
+
+ [1.9,)
+
+
+
+
+ default-jdk
+
+ (,1.8]
+
+
+
+ com.sun
+ tools
+ ${java.version}
+ system
+ ${toolsjar}
+
+
+
+
diff --git a/vjmxcli/src/main/assembly/vjmxcli.sh b/vjmxcli/src/main/assembly/vjmxcli.sh
index 391f9af8..85463d88 100644
--- a/vjmxcli/src/main/assembly/vjmxcli.sh
+++ b/vjmxcli/src/main/assembly/vjmxcli.sh
@@ -11,15 +11,61 @@ if [ ! -d "$JAVA_HOME" ] ; then
exit 1
fi
-TOOLSJAR="$JAVA_HOME/lib/tools.jar"
-if [ ! -f "$TOOLSJAR" ] ; then
- echo "$TOOLSJAR doesn't exist" >&2
- exit 1
+
+# returns the JDK version.
+# 8 for 1.8.0_nn, 9 for 9-ea etc, and "no_java" for undetected
+GET_JDK_VERSION() {
+ local result
+ local java_cmd
+ if [[ -n $(type -p java) ]]
+ then
+ java_cmd=java
+ elif [[ (-n "$JAVA_HOME") && (-x "$JAVA_HOME/bin/java") ]]
+ then
+ java_cmd="$JAVA_HOME/bin/java"
+ fi
+ local IFS=$'\n'
+ # remove \r for Cygwin
+ local lines=$("$java_cmd" -Xms32M -Xmx32M -version 2>&1 | tr '\r' '\n')
+ if [[ -z $java_cmd ]]
+ then
+ result=no_java
+ else
+ for line in $lines; do
+ if [[ (-z $result) && ($line = *"version \""*) ]]
+ then
+ local ver=$(echo $line | sed -e 's/.*version "\(.*\)"\(.*\)/\1/; 1q')
+ # on macOS, sed doesn't support '?'
+ if [[ $ver = "1."* ]]
+ then
+ result=$(echo $ver | sed -e 's/1\.\([0-9]*\)\(.*\)/\1/; 1q')
+ else
+ result=$(echo $ver | sed -e 's/\([0-9]*\)\(.*\)/\1/; 1q')
+ fi
+ fi
+ done
+ fi
+ echo "$result"
+}
+
+JDK_VERSION=$(GET_JDK_VERSION)
+echo "JDK_VERSION : $JDK_VERSION"
+
+# jdk 8 and before
+if [[ $JDK_VERSION -le 8 ]]; then
+ TOOLSJAR="$JAVA_HOME/lib/tools.jar"
+ if [ ! -f "$TOOLSJAR" ] ; then
+ echo "$TOOLSJAR doesn't exist" >&2
+ exit 1
+ fi
+ JAVA_OPTS="-Xms256m -Xmx256m -XX:NewRatio=1 -Xss256k -XX:+UseSerialGC -XX:CICompilerCount=2 -Xverify:none -XX:AutoBoxCacheMax=20000"
+else
+ # jdk 9 or later
+ JAVA_OPTS="-Xms256m -Xmx256m -XX:NewRatio=1 -Xss256k -XX:+UseSerialGC -XX:CICompilerCount=2 -XX:AutoBoxCacheMax=20000"
fi
-DIR=$( cd $(dirname $0) ; pwd -P )
-JAVA_OPTS="-Xms96m -Xmx96m -Xmn64m -Xss256k -XX:+UseSerialGC -Djava.compiler=NONE -Xverify:none -XX:AutoBoxCacheMax=20000"
+DIR=$( cd $(dirname $0) ; pwd -P )
"$JAVA_HOME"/bin/java $JAVA_OPTS -cp "$DIR/vjmxcli.jar:$TOOLSJAR" com.vip.vjtools.jmx.Client $*
\ No newline at end of file
diff --git a/vjmxcli/src/main/java/com/vip/vjtools/jmx/Client.java b/vjmxcli/src/main/java/com/vip/vjtools/jmx/Client.java
index 63777f1e..06adf212 100644
--- a/vjmxcli/src/main/java/com/vip/vjtools/jmx/Client.java
+++ b/vjmxcli/src/main/java/com/vip/vjtools/jmx/Client.java
@@ -142,7 +142,7 @@ protected String[] parseUserpass(final String userpass) {
if (index <= 0) {
throw new RuntimeException("Unable to parse: " + userpass);
}
- return new String[] { userpass.substring(0, index), userpass.substring(index + 1) };
+ return new String[]{userpass.substring(0, index), userpass.substring(index + 1)};
}
/**
@@ -152,7 +152,7 @@ protected String[] parseUserpass(final String userpass) {
*/
protected static Map formatCredentials(final String login, final String password) {
Map env = null;
- String[] creds = new String[] { login, password };
+ String[] creds = new String[]{login, password};
env = new HashMap(1);
env.put(JMXConnector.CREDENTIALS, creds);
return env;
@@ -202,39 +202,49 @@ public static String getLocalConnectorAddress(String pid) throws IOException {//
}
// 3. 未启动,尝试启动
- // JDK8后有更直接的vm.startLocalManagementAgent()方法
- String home = vm.getSystemProperties().getProperty("java.home");
-
- // Normally in ${java.home}/jre/lib/management-agent.jar but might
- // be in ${java.home}/lib in build environments.
-
- String agentPath = home + File.separator + "jre" + File.separator + "lib" + File.separator
- + "management-agent.jar";
- File f = new File(agentPath);
- if (!f.exists()) {
- agentPath = home + File.separator + "lib" + File.separator + "management-agent.jar";
- f = new File(agentPath);
+ int version = getJavaMajorVersion(vm.getSystemProperties().getProperty("java.specification.version"));
+ if (version >= 8) {
+ vm.startLocalManagementAgent();
+ agentProps = vm.getAgentProperties();
+ address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+ } else {
+ // JDK8后有更直接的vm.startLocalManagementAgent()方法
+ String home = vm.getSystemProperties().getProperty("java.home");
+ // Normally in ${java.home}/jre/lib/management-agent.jar but might
+ // be in ${java.home}/lib in build environments.
+ String agentPath = home + File.separator + "jre" + File.separator + "lib" + File.separator
+ + "management-agent.jar";
+
+ File f = new File(agentPath);
if (!f.exists()) {
- throw new IOException("Management agent not found");
+ agentPath = home + File.separator + "lib" + File.separator + "management-agent.jar";
+ f = new File(agentPath);
+ if (!f.exists()) {
+ throw new IOException("Management agent not found");
+ }
}
- }
- agentPath = f.getCanonicalPath();
- try {
- vm.loadAgent(agentPath, "com.sun.management.jmxremote");
- } catch (AgentLoadException x) {
- IOException ioe = new IOException(x.getMessage());
- ioe.initCause(x);
- throw ioe;
- } catch (AgentInitializationException x) {
- IOException ioe = new IOException(x.getMessage());
- ioe.initCause(x);
- throw ioe;
- }
+ agentPath = f.getCanonicalPath();
+ try {
+ vm.loadAgent(agentPath, "com.sun.management.jmxremote");
+ } catch (AgentLoadException x) {
+ // 高版本 attach 低版本jdk 抛异常:com.sun.tools.attach.AgentLoadException: 0,实际上是成功的;
+ // 根因: HotSpotVirtualMachine.loadAgentLibrary 高版本jdk实现不一样了
+ if (!"0".equals(x.getMessage())) {
+ IOException ioe = new IOException(x.getMessage());
+ ioe.initCause(x);
+ throw ioe;
+ }
+ } catch (AgentInitializationException x) {
+ IOException ioe = new IOException(x.getMessage());
+ ioe.initCause(x);
+ throw ioe;
+ }
- // 4. 再次获取connector address
- agentProps = vm.getAgentProperties();
- address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+ // 4. 再次获取connector address
+ agentProps = vm.getAgentProperties();
+ address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+ }
if (address == null) {
throw new IOException("Fails to find connector address");
@@ -311,7 +321,7 @@ protected Object[] execute(final String hostport, final String login, final Stri
public Object[] executeOneCmd(final String hostport, final String login, final String password,
final String beanname, final String command) throws Exception {
- return execute(hostport, login, password, beanname, new String[] { command }, true);
+ return execute(hostport, login, password, beanname, new String[]{command}, true);
}
/**
@@ -386,7 +396,7 @@ protected static Object[] doBeans(final MBeanServerConnection mbsc, final Object
}
buffer.append("\n");
}
- result = new String[] { buffer.toString() };
+ result = new String[]{buffer.toString()};
}
return result;
}
@@ -404,7 +414,7 @@ protected static Object[] doBean(MBeanServerConnection mbsc, ObjectInstance inst
throws Exception {
// If no command, then print out list of attributes and operations.
if (command == null || command.length <= 0) {
- return new String[] { listOptions(mbsc, instance) };
+ return new String[]{listOptions(mbsc, instance)};
}
// Maybe multiple attributes/operations listed on one command line.
@@ -614,8 +624,8 @@ protected static Object doAttributeOperation(MBeanServerConnection mbsc, ObjectI
// Get first attribute of name 'cmd'. Assumption is no method
// overrides. Then, look at the attribute and use its type.
MBeanAttributeInfo info = (MBeanAttributeInfo) getFeatureInfo(infos, parse.getCmd());
- java.lang.reflect.Constructor c = Class.forName(info.getType()).getConstructor(new Class[] { String.class });
- Attribute a = new Attribute(parse.getCmd(), c.newInstance(new Object[] { parse.getArgs()[0] }));
+ java.lang.reflect.Constructor c = Class.forName(info.getType()).getConstructor(new Class[]{String.class});
+ Attribute a = new Attribute(parse.getCmd(), c.newInstance(new Object[]{parse.getArgs()[0]}));
mbsc.setAttribute(instance.getObjectName(), a);
return null;
}
@@ -644,8 +654,8 @@ protected static Object doBeanOperation(MBeanServerConnection mbsc, ObjectInstan
for (int i = 0; i < paraminfosLength; i++) {
MBeanParameterInfo paraminfo = paraminfos[i];
java.lang.reflect.Constructor c = Class.forName(paraminfo.getType())
- .getConstructor(new Class[] { String.class });
- params[i] = c.newInstance(new Object[] { parse.getArgs()[i] });
+ .getConstructor(new Class[]{String.class});
+ params[i] = c.newInstance(new Object[]{parse.getArgs()[i]});
signature[i] = paraminfo.getType();
}
result = mbsc.invoke(instance.getObjectName(), parse.getCmd(), params, signature);
@@ -760,4 +770,20 @@ public synchronized String format(LogRecord record) {
}
}
+ private static int getJavaMajorVersion(String javaSpecificationVersion) {
+ if (javaSpecificationVersion.startsWith("1.8")) {
+ return 8;
+ } else if (javaSpecificationVersion.startsWith("1.7")) {
+ return 7;
+ } else if (javaSpecificationVersion.startsWith("1.6")) {
+ return 6;
+ } else {
+ try {
+ return Integer.parseInt(javaSpecificationVersion);
+ } catch (NumberFormatException e) {
+ return 0;
+ }
+ }
+ }
+
}
diff --git a/vjmxcli/src/main/java/com/vip/vjtools/jmx/ExtraCommand.java b/vjmxcli/src/main/java/com/vip/vjtools/jmx/ExtraCommand.java
index 71e00469..b3c8af2d 100644
--- a/vjmxcli/src/main/java/com/vip/vjtools/jmx/ExtraCommand.java
+++ b/vjmxcli/src/main/java/com/vip/vjtools/jmx/ExtraCommand.java
@@ -24,9 +24,9 @@ private void gcUtilCommand(MBeanServerConnection mbsc, int interval) throws Exce
String[] commands;
if (getJavaVersion(mbsc) > 7) {
- commands = new String[] { "S", "S", "E", "O", "M", "CCS", "YGC", "YGCT", "FGC", "FGCT", "GCT" };
+ commands = new String[]{"S", "S", "E", "O", "M", "CCS", "YGC", "YGCT", "FGC", "FGCT", "GCT"};
} else {
- commands = new String[] { "S", "S", "E", "O", "P", "YGC", "YGCT", "FGC", "FGCT", "GCT" };
+ commands = new String[]{"S", "S", "E", "O", "P", "YGC", "YGCT", "FGC", "FGCT", "GCT"};
}
for (String commmand : commands) {
@@ -84,14 +84,18 @@ private Object[] executGCutil(final String[] commands, GCutilExpression gcE) thr
public static int getJavaVersion(final MBeanServerConnection mbsc) throws Exception {
Object version = mbsc.getAttribute(Client.getObjectName("java.lang:type=Runtime"), "SpecVersion");
String javaVersion = version.toString();
- if (javaVersion.startsWith("1.8") || Double.parseDouble(javaVersion.substring(0, 3)) > 1.7) {
+ if (javaVersion.startsWith("1.8")) {
return 8;
} else if (javaVersion.startsWith("1.7")) {
return 7;
} else if (javaVersion.startsWith("1.6")) {
return 6;
} else {
- return 0;
+ try {
+ return Integer.parseInt(javaVersion);
+ } catch (NumberFormatException e) {
+ return 0;
+ }
}
}
}
diff --git a/vjmxcli/src/main/java/com/vip/vjtools/jmx/GCutilExpression.java b/vjmxcli/src/main/java/com/vip/vjtools/jmx/GCutilExpression.java
index 3ddcd5f4..9aa64b23 100644
--- a/vjmxcli/src/main/java/com/vip/vjtools/jmx/GCutilExpression.java
+++ b/vjmxcli/src/main/java/com/vip/vjtools/jmx/GCutilExpression.java
@@ -103,10 +103,16 @@ public Double getYGCT() throws Exception {
}
public Object getFGC() throws Exception {
+ if (fgcCollector == null) {
+ return 0;
+ }
return getAttribute(fgcCollector, COLLECTION_COUNT_ATTRIBUTE);
}
public Double getFGCT() throws Exception {
+ if (fgcCollector == null) {
+ return 0.0;
+ }
return Double.parseDouble(getAttribute(fgcCollector, COLLECTION_TIME_ATTRIBUTE).toString()) / 1000;
}