Skip to content

Commit 529a6d5

Browse files
committed
getMainClass(), getMainArgs() and getCommandLine() methods added to JmxModel
1 parent 04b707c commit 529a6d5

File tree

4 files changed

+161
-2
lines changed

4 files changed

+161
-2
lines changed

visualvm/jmx/src/org/graalvm/visualvm/jmx/impl/JmxModelImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,10 @@ public boolean isTakeThreadDumpSupported() {
369369
return support.getThreadBean() != null && !support.isReadOnlyConnection();
370370
}
371371

372+
public String getCommandLine() {
373+
return getJmxSupport().getCommandLine();
374+
}
375+
372376
private JmxSupport getJmxSupport() {
373377
synchronized (jmxSupportLock) {
374378
if (jmxSupport == null) {

visualvm/jmx/src/org/graalvm/visualvm/jmx/impl/JmxSupport.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ public class JmxSupport {
6767
"com.sun.management:type=DiagnosticCommand"; // NOI18N
6868
private static final String ALL_OBJECTS_OPTION = "-all"; // NOI18N
6969
private static final String HISTOGRAM_COMMAND = "gcClassHistogram"; // NOI18N
70+
private static final String CMDLINE_COMMAND = "vmCommandLine"; // NOI18N
71+
private static final String CMDLINE_PREFIX = "java_command: "; // NOI18N
7072

7173
private JvmMXBeans mxbeans;
7274
private JmxModel jmxModel;
@@ -404,4 +406,45 @@ private boolean hasDumpAllThreads() {
404406
return hasDumpAllThreads.booleanValue();
405407
}
406408
}
409+
410+
String getCommandLine() {
411+
if (jmxModel.getConnectionState() == ConnectionState.CONNECTED) {
412+
MBeanServerConnection conn = jmxModel.getMBeanServerConnection();
413+
try {
414+
ObjectName diagCommName = new ObjectName(DIAGNOSTIC_COMMAND_MXBEAN_NAME);
415+
416+
if (conn.isRegistered(diagCommName)) {
417+
Object vmCommandLine = conn.invoke(diagCommName,
418+
CMDLINE_COMMAND,
419+
new Object[] {},
420+
new String[] {}
421+
);
422+
if (vmCommandLine instanceof String) {
423+
return parseVMCommandLine((String) vmCommandLine);
424+
}
425+
}
426+
} catch (MalformedObjectNameException ex) {
427+
Exceptions.printStackTrace(ex);
428+
} catch (IOException ex) {
429+
LOGGER.log(Level.INFO,"getCommandLine", ex); // NOI18N
430+
} catch (InstanceNotFoundException ex) {
431+
Exceptions.printStackTrace(ex);
432+
} catch (MBeanException ex) {
433+
Exceptions.printStackTrace(ex);
434+
} catch (ReflectionException ex) {
435+
Exceptions.printStackTrace(ex);
436+
}
437+
}
438+
return null;
439+
}
440+
441+
private String parseVMCommandLine(String vmCommandLine) {
442+
String[] lines = vmCommandLine.split("\\r?\\n");
443+
for (String line : lines) {
444+
if (line.startsWith(CMDLINE_PREFIX)) {
445+
return line.substring(CMDLINE_PREFIX.length());
446+
}
447+
}
448+
return null;
449+
}
407450
}

visualvm/jvm/src/org/graalvm/visualvm/jvm/JVMImpl.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,8 +546,9 @@ protected void initStaticData() {
546546
vmName = jvmstatModel.getVmName();
547547
vmVendor = jvmstatModel.getVmVendor();
548548
} else {
549+
JmxModel jmxModel = getJmxModel();
549550
jvmArgs = jmxSupport.getJvmArgs();
550-
Properties prop = getJmxModel().getSystemProperties();
551+
Properties prop = jmxModel.getSystemProperties();
551552
if (prop != null) {
552553
vmVersion = prop.getProperty("java.vm.version"); // NOI18N
553554
javaVersion = prop.getProperty("java.version"); // NOI18N
@@ -556,7 +557,10 @@ protected void initStaticData() {
556557
vmName = prop.getProperty("java.vm.name"); // NOI18N
557558
vmVendor = prop.getProperty("java.vm.vendor"); // NOI18N
558559
}
559-
}
560+
commandLine = jmxModel.getCommandLine();
561+
mainArgs = jmxModel.getMainArgs();
562+
mainClass = jmxModel.getMainClass();
563+
}
560564
staticDataInitialized = true;
561565
}
562566
}

visualvm/tools/src/org/graalvm/visualvm/tools/jmx/JmxModel.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.beans.PropertyChangeListener;
3232
import java.beans.PropertyChangeSupport;
3333
import java.util.Properties;
34+
import java.util.regex.Pattern;
3435
import javax.management.MBeanServerConnection;
3536
import javax.management.remote.JMXServiceURL;
3637

@@ -71,6 +72,9 @@
7172
*/
7273
public abstract class JmxModel extends Model {
7374

75+
private static final String JAR_SUFFIX = ".jar"; // NOI18N
76+
private static final Pattern MODULE_MAIN_CLASS_PATTERN = Pattern.compile("^(\\w+\\.)*\\w+/(\\w+\\.)+\\w+$");
77+
7478
protected PropertyChangeSupport propertyChangeSupport =
7579
new AsyncPropertyChangeSupport(this);
7680
/**
@@ -236,4 +240,108 @@ public void removePropertyChangeListener(PropertyChangeListener listener) {
236240
* @since VisualVM 1.3
237241
*/
238242
public abstract void setFlagValue(String name,String value);
243+
244+
/**
245+
* Returns the Java virtual machine command line.
246+
*
247+
* @return String - contains the command line of the target Java
248+
* application or <CODE>NULL</CODE> if the
249+
* command line cannot be determined.
250+
*/
251+
public abstract String getCommandLine();
252+
253+
/**
254+
* Return the arguments to the main class for the target Java application.
255+
* Returns the arguments to the main class. If the arguments can't be
256+
* found, <code>null</code> is returned.
257+
*
258+
* @return String - contains the arguments to the main class for the
259+
* target Java application or the <code>null</code>
260+
* if the command line cannot be determined.
261+
*/
262+
263+
public String getMainArgs() {
264+
String commandLine = getCommandLine();
265+
266+
if (commandLine != null) {
267+
String arg0 = getFirstArgument(commandLine);
268+
269+
int firstSpace = arg0.length();
270+
if (firstSpace < commandLine.length()) {
271+
return commandLine.substring(firstSpace);
272+
}
273+
}
274+
return null;
275+
}
276+
277+
/**
278+
* Return the main class for the target Java application.
279+
* Returns the main class, if the application started with the <em>-jar</em> option,
280+
* it tries to determine main class from the jar file. If
281+
* the jar file is not accessible, the main class is simple
282+
* name of the jar file.
283+
* @return String - the main class of the target Java
284+
* application.
285+
*/
286+
public String getMainClass() {
287+
String commandLine = getCommandLine();
288+
289+
if (commandLine != null) {
290+
String mainClassName = getFirstArgument(commandLine);
291+
292+
if (mainClassName.endsWith(JAR_SUFFIX)) {
293+
mainClassName = mainClassName.replace('\\', '/');
294+
int index = mainClassName.lastIndexOf('/');
295+
if (index != -1) {
296+
mainClassName = mainClassName.substring(index + 1);
297+
}
298+
} else if (MODULE_MAIN_CLASS_PATTERN.matcher(mainClassName).find()) {
299+
return mainClassName.substring(mainClassName.indexOf('/')+1);
300+
}
301+
mainClassName = mainClassName.replace('\\', '/').replace('/', '.');
302+
return mainClassName;
303+
}
304+
return null;
305+
}
306+
307+
private String getFirstArgument(String commandLine) {
308+
String mainClassName = null;
309+
310+
// search for jar file
311+
int jarIndex = commandLine.indexOf(JAR_SUFFIX);
312+
if (jarIndex != -1) {
313+
String jarFile = commandLine.substring(0,jarIndex+JAR_SUFFIX.length());
314+
// if this is not end of commandLine check that jar file is separated by space from other arguments
315+
if (jarFile.length() == commandLine.length() || commandLine.charAt(jarFile.length()) == ' ') {
316+
// jarFile must be on classpath
317+
String classPath = getClassPath();
318+
if (classPath != null && classPath.indexOf(jarFile) != -1) {
319+
mainClassName = jarFile;
320+
}
321+
}
322+
}
323+
// it looks like ordinary commandline with main class
324+
if (mainClassName == null) {
325+
int firstSpace = commandLine.indexOf(' ');
326+
if (firstSpace > 0) {
327+
mainClassName = commandLine.substring(0, firstSpace);
328+
} else {
329+
mainClassName = commandLine;
330+
}
331+
}
332+
return mainClassName;
333+
}
334+
335+
/**
336+
* Returns the Java virtual machine implementation version.
337+
* This method is equivalent to {@link System#getProperty
338+
* System.getProperty("java.class.path")}.
339+
*
340+
* @return the Java virtual machine classpath.
341+
*
342+
* @see java.lang.System#getProperty
343+
*/
344+
private String getClassPath() {
345+
return getSystemProperties().getProperty("java.class.path"); // NOI18N
346+
}
239347
}

0 commit comments

Comments
 (0)