如何在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