在localhost上运行JVM的列表
如何在Java 6+中获取localhost上运行的JVM列表及其规范(即Java版本,运行线程等)?
Java API是否提供此类function? 是否有可以执行此操作的Java库?
您可以使用jps
,一个随jvm一起分发的命令行工具。 但是,我不知道它有任何普通的Java API。 但是,JConsole可以做你所要求的,所以我看看它的来源。 这是非常可怕的,但在环顾四周时,我发现了对jVisualVM类的引用,当你指定Java 6+时,可以看到它们。 这是我发现的:
这些类都在sun.tools
,所以首先你必须找到JVM附带的jconsole.jar
(当然是假定Sun JVM)并将它添加到类路径中。 然后,可以获得活动VM的快速列表:
public static void main(final String[] args) { final Map virtualMachines = LocalVirtualMachine.getAllVirtualMachines(); for (final Entry entry : virtualMachines.entrySet()) { System.out.println(entry.getKey() + " : " + entry.getValue().displayName()); } }
一旦获得对JVM的引用,就可以使用Attach API与它们进行通信。
\jdk\bin
目录中的jps
打印一个正在运行的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
实际上,您可以使用Attach API获取JVM列表,而无需使用jconsole.jar
。
下面演示了如何获取本地运行的JVM列表,获取一些属性,通过JMX连接到每个JVM,以及通过该连接获取更多信息。
// ... import com.sun.tools.attach.*; import javax.management.*; // ... List 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
。 关于JMX的更多内容可以在这里找到,我从这个问题的另一个答案的评论中得到了。 上面的一些代码来自两个链接。
注意 :至少对我来说,我必须将tools.jar
添加到bootstrap类路径中以便运行:
$ java -Xbootclasspath/a:${JAVA_HOME}/lib/tools.jar -jar
除了jps
还有jstack
工具,可以打印出任何java进程的堆栈跟踪。 其输出的开头包含VM版本,然后是带有堆栈跟踪的线程列表。
我认为所有三个jps,jstack和jconsole都是基于javax.management.*
和java.lang.management
的Java Management Beans API实现的,所以请查看有关如何在自己的程序中执行此操作的更多信息。
编辑:这是管理内容的文档索引 。 特别有趣的是使用JMX API进行监控和管理 。
(是的,它不仅适用于自己的VM,也适用于同一系统上的其他VM,甚至适用于远程系统上的其他VM,如果它们公开了正确的接口。)
我今天发现,这基本上就是JPS的作用:只需列出文件夹/ tmp / hsperfdata_foo / ,其中foo是运行JVM的用户。
由于某些未知原因,有时候JVM被杀死时不会删除那里的文件。
以下是源代码的链接:
PerfDataFile.java
LocalVmManager
如果你只需要运行带有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. * * 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 getActiveLocalVms() { List result = new LinkedList (); MonitoredHost monitoredHost; Set 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的一些变体,默认情况下它在classpath上,有些你必须添加它。 使用Maven依赖项执行此操作有点棘手,需要systemPath。
如果您想要更多信息,请点击列表,查看PaŭloEbermann的链接 – 使用JMX API进行监控和管理 。
VirtualMachine vm = VirtualMachine.attach(pid);
您从列表中获得的PID。 然后将您的代理插入(未经考虑的)Java(或任何JVM)应用程序。
vm.loadAgent(agentJarLibraryFullPath);
然后通过JMXConnector与您的代理进行通信。 您的代理可以为您收集所有统计信息。 我没有亲自尝试过。 您甚至可以通过这种方式检测(修改)运行时代码。 Profilers使用它。
我不知道Java 6,但我认为你可以通过从命令行运行jconsole来做到。
此外,如果您在* nix平台上,您可以发出如下命令:
ps aux | grep java
祝你好运!
据我所知,jps提供了使用它所属的jvm启动的进程列表。 如果您安装了多个JDK,我认为它不会有所帮助。 如果你想要一个所有java进程的列表,你必须使用“ps -ef | grep java”。 我见过很多次JVsualVM无法识别特定主机上运行的所有java进程。 如果您的要求特定于JVM启动的流程,则上述建议将适用。
- Android Parcelable – 使用通用数据类型将数据读/写到Parcel
- 图像不是使用BitmapFactory.decodeByteArray创建的
- Android studio – 如何保存以前活动中选择的数据
- 在Edittext中输入十进制值?
- 使用CheckBoxPreference禁用或启用移动数据?
- 创建一个较慢的过渡。 TransitionManager.beginDelayedTransition(); 太快了
- Eclipse Android中的“java堆大小”错误?
- FragmentActivity上ActionBar上的空指针exception
- 如何在新电子邮件到达Android时执行一些代码?