如何在Java 6+中獲得本地主機上正在運行的JVM的列表及其規格(即Java版本,正在運行的線程等)?本地主機上正在運行的JVM的列表
Java API是否提供了這些功能?有沒有可以做到這一點的Java庫?
如何在Java 6+中獲得本地主機上正在運行的JVM的列表及其規格(即Java版本,正在運行的線程等)?本地主機上正在運行的JVM的列表
Java API是否提供了這些功能?有沒有可以做到這一點的Java庫?
您可以使用jps
,與JVM分發的命令行工具。不過,我還沒有意識到它有任何正常的Java API。不過,JConsole可以做你想問的,所以我看看它的來源。這非常可怕,但是在四處尋找時,我發現了對jVisualVM類的引用,在您指定Java 6+時可以看到。這裏是我發現的:
這些類都在sun.tools
,所以首先你必須找到你的JVM附帶的jconsole.jar
(當然假設是Sun JVM)並將它添加到你的類路徑中。然後激活虛擬機的快速正骯髒的上市可以得到這樣的:
public static void main(final String[] args) {
final Map<Integer, LocalVirtualMachine> virtualMachines = LocalVirtualMachine.getAllVirtualMachines();
for (final Entry<Integer, LocalVirtualMachine> entry : virtualMachines.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue().displayName());
}
}
一旦你得到了你的JVM的引用,你可以與他們使用Attach API通信。
非常有趣!我也剛剛發現這個解決方案http://download.oracle.com/javase/6/docs/technotes/guides/management/agent.html#gdhkz。它使用JAVA_HOME/lib中的tools.jar(你必須將它添加到你的類路徑中)。 – fsarradin 2011-03-05 15:22:26
jps
在\jdk\bin
目錄中打印正在運行的Java進程的列表,但不打印它們的規格。一些運行條件可供選擇:
C:\Java\jdk1.6.0_23\bin>jps -mlv
4660 -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx512m -XX:MaxPermSize=256m
6996 sun.tools.jps.Jps -mlv -Dapplication.home=C:\Java\jdk1.6.0_23 -Xms8m
我不知道Java 6,但我認爲你可以通過從命令行運行jconsole來完成。
另外,如果你是一個* nix的平臺,你可以這樣這樣發出命令:
ps aux | grep java
祝你好運!
你是不是指'| grep java'? – 2011-03-04 23:22:56
除jps
外,還有jstack
工具,可以打印出任何java進程的堆棧跟蹤。其輸出的開始包含VM版本,然後是帶有堆棧跟蹤的線程列表。
我想的JPS,jstack和JConsole的所有三個是基於javax.management.*
和java.lang.management
Java管理豆API實現的,所以在那裏尋找如何做到這一點在自己的程序的詳細信息。
編輯:這裏是documentation index的管理的東西。 特別有趣似乎點Monitoring and Management Using the JMX API。
(是的,它不僅適用於自己的虛擬機,也爲其他的人在同一系統上,甚至對遠程系統上的,如果他們暴露右側接口)。
我相信'java.lang.management'包含類,同時允許您檢查當前正在運行的JVM,而不是與您在同一臺計算機上的其他JVM。 – 2011-03-04 23:31:36
我站好了!這是好東西。 – 2011-03-05 00:03:32
謝謝你的鏈接:) – fsarradin 2011-03-05 15:25:46
據我所知jps提供使用它所屬的jvm啓動的進程列表。如果您安裝了多個JDK,我認爲這不會有幫助。 如果你想要一個所有java進程的列表,你必須使用「ps -ef | grep java」。我曾多次看到JVsualVM無法識別在特定主機上運行的所有Java進程。如果您的需求是特定於JVM啓動的進程的,則上述建議將適用。
今天我發現,這基本上就是JPS所做的:簡單地列出文件夾/tmp/hsperfdata_foo/其中foo是運行JVM的用戶。
由於某些未知原因,有時在JVM被終止時,那裏的文件不會被刪除。
這裏是鏈接到源代碼:
如果你只需要使用的PID運行的JVM的列表這個工作對我來說:
package my.code.z025.util;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;
/**
* Get list of all local active JVMs
*/
public class ActiveJavaVirtualMachineExplorer {
/**
* Represents successfully captured active java virtual machine
*/
public static class ActiveVm {
private int pid;
private String name;
... shortened ...
}
/**
* Represents unsuccessfully captured active java virtual machine, a failure.
* Keep cause exception.
*/
public static class FailedActiveVm extends ActiveVm {
private Exception cause;
... shortened ...
}
/**
* Get list of all local active JVMs.
* <p>
* Returns something like:
* ActiveVm [pid=7992, name=my.code.z025.util.launch.RunHttpServer]
* ActiveVm [pid=6972, name=]
* ActiveVm [pid=8188, name=my.code.z025.util.launch.RunCodeServer]
* ActiveVm [pid=4532, name=org.eclipse.jdt.internal.junit.runner.RemoteTestRunner]
* The pid=6972 must be Eclipse. So this approach is not water tight.
*/
public static List<ActiveVm> getActiveLocalVms() {
List<ActiveVm> result = new LinkedList<ActiveVm>();
MonitoredHost monitoredHost;
Set<Integer> activeVmPids;
try {
monitoredHost = MonitoredHost.getMonitoredHost(new HostIdentifier((String) null));
activeVmPids = monitoredHost.activeVms();
for (Integer vmPid : activeVmPids) {
try {
MonitoredVm mvm = monitoredHost.getMonitoredVm(new VmIdentifier(vmPid.toString()));
result.add(new ActiveVm(vmPid.intValue(), MonitoredVmUtil.mainClass(mvm, true)));
mvm.detach();
} catch (Exception e) {
result.add(new FailedActiveVm(vmPid.intValue(), e));
}
}
return result;
} catch (java.net.URISyntaxException e) {
throw new InternalError(e.getMessage());
} catch (MonitorException e) {
throw new InternalError(e.getMessage());
}
}
}
應用不必像任何特殊的命令行參數那樣運行。無需激活JMX。
儘管如此,並非所有JVM應用程序都能正常運行。對於Eclipse,我只看到PID,但看不到類名或命令行。
您必須將tool.jar
添加到您的類路徑中,它包含軟件包sun.jvmstat.*
。 tool.jar
是JDK的一部分。有了JDK/OS的一些變體,默認情況下它是在類路徑上的,有些則需要添加它。這樣做與Maven依賴關係有點棘手,systemPath是必需的。
如果您需要更多,然後只是列表,請檢查PaŭloEbermann - Monitoring and Management Using the JMX API的鏈接。
VirtualMachine vm = VirtualMachine.attach(pid);
其中PID從列表中獲得。然後將您的代理插入(未經確認的)Java(或任何JVM)應用程序。
vm.loadAgent(agentJarLibraryFullPath);
然後通過JMXConnector與您的代理進行通信。您的代理可以爲您收集所有統計數據。我沒有親自嘗試過。你甚至可以用這種方式來測試(修改)運行時間代碼。 Profiler使用它。
實際上,您可以使用Attach API獲取JVM列表,而無需使用jconsole.jar
。
以下演示獲取本地運行的JVM列表,獲取一些屬性,通過JMX連接到每個JVM,並通過該連接獲取更多信息。
// ...
import com.sun.tools.attach.*;
import javax.management.*;
// ...
List<VirtualMachineDescriptor> descriptors = VirtualMachine.list();
for (VirtualMachineDescriptor descriptor : descriptors) {
System.out.println("Found JVM: " + descriptor.displayName());
try {
VirtualMachine vm = VirtualMachine.attach(descriptor);
String version = vm.getSystemProperties().getProperty("java.runtime.version");
System.out.println(" Runtime Version: " + version);
String connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
if (connectorAddress == null) {
vm.startLocalManagementAgent();
connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
}
JMXServiceURL url = new JMXServiceURL(connectorAddress);
JMXConnector connector = JMXConnectorFactory.connect(url);
MBeanServerConnection mbs = connector.getMBeanServerConnection();
ObjectName threadName = new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
Integer threadCount = (Integer)mbs.getAttribute(threadName, "ThreadCount");
System.out.println(" Thread count: " + threadCount);
}
catch (Exception e) {
// ...
}
}
可用的MXBean
的列表是here。有關JMX的更多信息,請參閱here,我從another answer的評論中獲得了此問題。上面的代碼來自兩個鏈接。
注意:至少對我來說,我不得不添加tools.jar
自舉類路徑它來運行:
$ java -Xbootclasspath/a:${JAVA_HOME}/lib/tools.jar -jar <jar>
LocalVirtualMachine在Java8中沒有太多的可用,這個答案現在是正確的 – loicmathieu 2016-08-22 14:34:52
的VisualVM可以做,所以必須有一個辦法,雖然可能不是一件容易的一個。 – biziclop 2011-03-04 23:10:20