一、JPS的基本用法
JPS可用于查看当前运行的Java进程信息。在命令行中输入“jps”即可查看当前运行的所有Java进程PID和进程名。
$ jps 1234 Main 5678 Tomcat 8910 Jps
其中,PID表示进程ID,进程名为启动Java进程时所指定的主类的名称。
如果要查看指定Java进程的PID,可以通过“-l”参数查看完整的进程名,然后通过grep命令过滤:
$ jps -l |grep Main 1234 Main
除了“-l”参数之外,JPS还支持其他常用的参数:
- -m:显示进程中启动主类时的参数
- -v:显示进程中启动主类时的JVM参数
- -q:只输出PID
二、使用JPS定位Java进程的问题
JPS除了可以查看Java进程的状态信息,还可以用于定位Java进程的问题。以下是几种常见的问题:
1. Java进程OOM
如果Java进程遇到OOM (内存溢出)问题,可以通过JPS查看对应的进程ID,并查看内存情况。
$ jps 1234 Main $ jstat -gcutil 1234 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 85.19 73.00 86.50 68.63 349 4.131 11 0.705 4.836
jstat命令用于监视Java虚拟机的各种运行状态,例如垃圾回收情况。以上命令将输出对应进程的堆内存状态。从中可以看到目前堆内存已经使用了86.50%。
2. Java进程卡死
如果Java进程卡死,可以使用JPS查看对应的进程ID,并使用jstack命令查看堆栈信息。使用jstack命令可以查看Java进程的堆栈信息,定位卡死的程序段。
$ jps 1234 Main $ jstack 1234
三、JPS与Java Management Extensions (JMX)
Java Management Extensions (JMX) 是一种Java平台管理系统。JMX提供了一组标准API用于管理和监视Java应用程序,可以实现对应用程序的监控、控制和管理。
JPS与JMX结合使用可以监听Java进程的状态信息,包括内存、线程、GC情况等。使用JConsole (Java GUI监测工具) 和jvisualvm (Java VisualVM工具) 可以以图形化界面的形式展示各种指标。以下是几个常用的命令:
- jstatd:启动jstat监测服务
- jconsole:启动Java GUI监测工具
- jvisualvm:启动Java VisualVM工具
四、JPS命令的实际应用
JPS命令可以用于实际开发中的各种场景。以下是几个例子:
1. 检查Java进程是否启动
在自动化测试和运维中,我们需要检查Java进程是否正常启动。可以使用JPS命令来检查Java进程是否正常运行。
private boolean checkProcessRunning(String processName) { String line; String pidAndName; try { Process p = Runtime.getRuntime().exec("jps -l"); try (BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) { while ((line = input.readLine()) != null) { pidAndName = line.trim(); if (pidAndName.endsWith(processName)) { return true; } } } } catch (Exception err) { err.printStackTrace(); } return false; }
2. 获取Java进程信息
在应用程序中需要获取Java进程的状态信息,例如进程ID、内存、线程、GC情况等。可以使用JPS命令结合JMX API来获取Java进程的状态信息。
public class JvmInfo { private static MBeanServerConnection getMBeanServerConnection(int pid) throws IOException { JMXServiceURL serviceURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + getRegistryPort(pid) + "/jmxrmi"); JMXConnector jmxConnector = JMXConnectorFactory.connect(serviceURL); return jmxConnector.getMBeanServerConnection(); } private static int getRegistryPort(int pid) throws IOException { String command = String.format("service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", findRmiRegistryPort(pid)); JMXServiceURL jmxUrl = new JMXServiceURL(command); JMXConnector jmxConnector = JMXConnectorFactory.connect(jmxUrl, null); return jmxConnector.getServerConnection().getAddress().getPort(); } private static int findRmiRegistryPort(int pid) throws IOException { String pidString = String.valueOf(pid); String[] cmd = { "jps", "-v" }; Process p = Runtime.getRuntime().exec(cmd); BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = null; while ((line = input.readLine()) != null) { if (line.contains(pidString)) { return Integer.valueOf(line.split("-Dcom.sun.management.jmxremote.port=")[1].split("\\s+")[0]); } } return 0; } public static void printJvmInfo(int pid) throws IOException { MBeanServerConnection conn = getMBeanServerConnection(pid); MemoryMXBean memoryMXBean = ManagementFactory.newPlatformMXBeanProxy(conn, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class); System.out.println("heap memory usage : " + memoryMXBean.getHeapMemoryUsage()); System.out.println("non-heap memory usage : " + memoryMXBean.getNonHeapMemoryUsage()); ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy(conn, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class); System.out.println("thread count : " + threadMXBean.getThreadCount()); System.out.println("GC count : " + memoryMXBean.getCollectionCount()); for (GarbageCollectorMXBean gcMbean : ManagementFactory.getGarbageCollectorMXBeans()) { System.out.println(gcMbean.getName() + " GC count : " + gcMbean.getCollectionCount()); } } }
结论
本文中详细阐述了Java JPS的基本用法、与Java进程问题的定位、与JMX的结合使用和实际应用。通过JPS命令,可以更好地监测和管理Java应用程序。