前言
之前做的小功能jar管理应用,启动、停止,尤其停止需要用pid来停止应用,现在说下怎么获取。
当然,不需要记录pid也能停止应用,可以通过命令找到应用对应的pid,不过记录下来比较方便,后续还用到pid来获取端口号,利用java代理。
一、JMX是什么、可以做什么
什么是JMX
JMX(Java Management Extensions,即Java管理扩展)是一个为应用程序、设备、系统等植入管理功能的框架。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活的开发无缝集成的系统、网络和服务管理应用。- form baidu
好像看了也很迷,它能做什么?
JMX默认的MBean它能获取应用的信息,尤其是运行时的信息,可以知道实时内存、线程使用情况。同是也可以自定义对象MBean注册上去,目标应用可以获取到该对象,使用很灵活,譬如可以做配置值,动态改变。
二、JMX获取pid
既然它能获取应用信息,运行时信息,那怎么获取呢
首先在应用启动的是,添加启动参数
#开启 JMX 远程控制
-Dcom.sun.management.jmxremote
#目标应用ip
-Djava.rmi.server.hostname=
#监听端口号,不能与目标应用端口一致
-Dcom.sun.management.jmxremote.port=
#是否开启鉴权
-Dcom.sun.management.jmxremote.authenticate=false
#是否开启 SSL
-Dcom.sun.management.jmxremote.ssl=false
当开启权限(-Dcom.sun.management.jmxremote.authenticate=true)之后,需要添加账号密码
#密码文件 默认JAVA_HOME/conf/management/jmxremote.password
-Dcom.sun.management.jmxremote.password.file=
#权限文件 JAVA_HOME/conf/management/jmxremote.access
-Dcom.sun.management.jmxremote.access.file=
譬如:地址用127.0.0.1 port 12580
java -Dfile.encoding=utf-8 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote= -Dcom.sun.management.jmxremote.port=12580 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar D:\jarmanage\jarManage\jarStroage\8f34f6bbde5f40bbb375b5d35f8fcf0c\jar-manage\jar-manage.jar >> D:\jarmanage\jarManage\jarLog\8f34f6bbde5f40bbb375b5d35f8fcf0c\jar-manage\jar-manage.log
启动之后,我们可以找到jdk bin目录下面的jconsole.exe 启动会有一个连接界面,一个可视化监控
点击远程,输入上面jar启动给的127.0.0.1:12580,就可以看到应用运行情况了
咳咳,是不是很迷为啥要点击jconsole.exe连接远程看?跟我们在java后端获取pid有什么关系?
一个是知道有这个东西可以远程监视java应用运行情况,另外重点我们可以在上面看到有个Mbean的东西。
我们找到java.lang 可以看到OperatingSystem(可以获取操作系统相关的信息)、Memory(可以获取内存使用情况信息)、Runtime(可以获取运行时情况信息)、Threading(可以获取线程情况,巅峰线程、历史线程等)等对象,特别是Runtime对象的名称2188@xx的2188是不是很熟悉,这2188就是上面Jconsole连接时候本地进程-jar-manage对应的pid。
好了我们现在知道从哪里可以获取到pid!!
嗯,到在java后端,用上面的远程地址、端口怎么获取pid了
写一个main方法执行。。
public static void main(String[] args) {
String ip = "127.0.0.1";
Integer port = 12580;
JMXConnector connector = null;
String jmxURL = "service:jmx:rmi:///jndi/rmi://" + ip + ":" + port + "/jmxrmi";
try {
JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
Map<String, Object> map = new HashMap<String, Object>();
//账号密码,之前没有开启权限,这里传个空数组就好,按实际填
// String[] credentials = new String[] { "monitorRole", "QED" };
String[] credentials = new String[] {};
map.put("jmx.remote.credentials", credentials);
connector = JMXConnectorFactory.connect(serviceURL, map);
MBeanServerConnection mbsc = connector.getMBeanServerConnection();
MemoryMXBean memoryMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
RuntimeMXBean runtimeMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class);
ThreadMXBean threadMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.newPlatformMXBeanProxy(mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
String jvmName = runtimeMXBean.getName();
System.out.println("pid:" + jvmName.split("@")[0]);
} catch (Exception e) {
e.getStackTrace();
}
可以看到获取到pid了。
嗯~,获取pid过程就这样了。
关于MemoryMXBean、RuntimeMXBean、ThreadMXBean、OperatingSystemMXBean的相关信息可以去看下类里面是什么东西,另外我们可以用它做什么?譬如做一个实时监控系统?内存预警?那就是自由发挥了。
拓展
1、文章开头说了MBean是过注册到JMX上去,这怎么注册留给下一章,另外注册上去可以做什么也是值得思考的。
2、目标应用的port 就是利用ava代理和自定义MBean注册上去,然后本地应用就能获取目标应用的port了。
3、我的其中一个应用例子springboot jar、war包管理界面化_sakyoka的博客-CSDN博客,在jar 管理应用中获取pid就是重中之重。