探究java基础命令jps

探究基础命令JPS

javaer的世界中, jps是常用的命令。

sudo -u admin /opt/taobao/java/bin/jps -mlvV

输出如下:

0?wx_fmt=png

很方便。我们可以知道当前用户下正在跑的java进程有哪些。但是这个jps是如何拿到进程数据的呢? 我们来一探究竟。

0X01 从哪里读进程数据?

首要的是拿到jps命令的源码。

这个很多人都知道。相关的代码被编译打包到了tools.jar中。但是我们当然还是想看这部分的源码。所以有必要去 http://openjdk.java.net/ 下载一份。

来看sun.tools.jps.Jps:

0?wx_fmt=png

注意这一句 monitoredHost.activeVms()。 经过debug发现这里已经拿到了实际的进程列表。实际负责获取进程数据的是sun.jvmstat.perfdata.monitor.protocol.local.LocalVmManager

0?wx_fmt=png

那就进去看看sun.jvmstat.perfdata.monitor.protocol.local.LocalVmManager#activeVms:

0?wx_fmt=png

0?wx_fmt=png

0?wx_fmt=png

这里就很明显的可以看到了。jps命令在获取实际的进程ID时, 是去用户的临时目录下去拿进程ID的。具体的文件路径是:

tmp_dir + hsperfdata_user + pid

比如随意找一台日常机器:

0?wx_fmt=png

mac上临时目录的位置不一样

0?wx_fmt=png


0X02 谁写的进程数据?

好了,知道了是怎么读取之后,下一个要考虑的问题是,谁在什么时候把进程数据写到这里了?

我们已知现在写入的文件夹名称叫 hsperfdata_xxx。所以google一把。发现了以下的信息。

见https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

jvm中有如下命令

0?wx_fmt=png

可以看出UsePerfData是用来控制是否生成这个perf文件的。默认会打开,当打开后便会生成hsperfdata_userid目录。所以现在的问题是, jvm是如何处理这个选项的?

hotspot/src/share/vm/runtime/perfMemory.cpp

0?wx_fmt=png

OK。 我们可以继续看看。create_memory_region方法在不同的操作系统中会有不同的实现。所以我们这里开看看linux对应的实现,在/hotspot/src/os/linux/vm/perfMemory_linux.cpp

0?wx_fmt=png

这里的第一行PerfDisableSharedMem涉及到另外一个jvm的命令XX:+PerfDisableSharedMem, 用来控制perfdata的这部分内存是否可以被共享, 默认关闭。如果打开的话后果和把-XX:+UsePerfData关闭差不多,诸如jps,jstat,jmap等命令就没法用了。 直接看create_shared_memory():

0?wx_fmt=png

OK, 继续

0?wx_fmt=png

到这里情况差不多要明了。

  1. int vmid = os::current_process_id(); 这里获取了当前的进程id。

  2. get_user_name(geteuid()); 获取用户名

  3. get_user_tmp_dir() 获取临时目录

  4. get_sharedmem_filename() 获取对应的进程文件名, 文件名就是进程id

再来看看最后一步的create_sharedmem_resources方法, 其实大家看到fd这个变量就应该感知到这里是实际创建文件的地方了-_-

0?wx_fmt=png

  1. make_user_tmp_dir 确保用户临时目录存在

  2. ::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE) C++自身的open函数来操作文件, 如果该文件不存在, 那就新建一个

好了。到这里基本上整个链路就很清楚了。最后顺便梳理一下关于写这个文件的c++部分的调用关系:0?wx_fmt=png


0X03 总结

  1. hsperfdata_xxx文件夹很重要。存储了当前用户的进程数据。

  2. 要保证当前操作系统的临时文件目录对jvm用户可读可写。这包含两层意思。1).权限要match, 2).空间要够用

  3. hsperfdata_xxx中的进程id文件也很重要。

  4. A用户是否能看B用户的进程数据, sun在代码层面没有做控制。只是简单的判断了对方的进程文件是否有权限可读 file.canRead()

  5. 缺少了hsperfdata文件其实也没什么大不了的。但是会导致很多工具无法使用. 比如jps, jdb, jstat, jconsole等等。这些可都是排查问题的利器啊。貌似只有JMX是可以用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值