(二)Java基础工具学习

一、jps命令

1. 介绍

jps(Java Virtual Machine Process Status Tool)工具用于显示当前系统的进程情况,可以使用该命令查看当前服务器的Java进程,该工具比较简单,我们来看下:

[email protected]:~$ jps -help
usage: jps [-help]
       jps [-q] [-mlvV] []

Definitions:
    :      [:]

我们来简单看下它的命令格式:jps [参数] [hostid],其中参数为:

-q 仅显示Java进程id,不包含类名等其他信息
-m 输出传递给main方法的参数
-l 输出应用程序main class的完整包名或者 应用程序的jar文件完整路径名
-v 输出进程所对应的jvm参数
-V 输出通过flag文件传递到JVM中的参数(.hotspotrc文件或-XX:Flags=所指定的文件
-Joption 传递参数到vm,例如:-J-Xms48m

而hostid格式为:

[protocol:][[//]hostname][:port][/servername]
2. 使用

接下来,我们来简单看下它的使用。
1)首先,我们来看下该命令默认情况下的展示及加上相关参数的展示:

[email protected]:~$ jps
27075 BootStrap
3875 App
29049 Jps

可以看到,只展示进程名称及进程id,这里可以看到jps命令也开了一个进程,因为jps其实也是一个Java命令,也要占一个进程的;然后使用jps -l

[email protected]:~$ jps -l
27075 com.test.spring.boot.BootStrap
3875 com.test.log.App
29415 sun.tools.jps.Jps

展示进程id及进程对应的完整的包名称;
2)接下来使用jps -v

[email protected]:~$ jps -v
27075 BootStrap -Xms5120m -Xmx5120m -Xmn2560m -XX:MaxMetaspaceSize=128m -XX:MetaspaceSize=128m -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC ...(省略)
3875 App -Dfile.encoding=UTF-8 -Xms128m -Xmx512m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection ...(省略)
29455 Jps -Denv.class.path=.:/usr/java/jdk1.8.0_66/lib/tools.jar:/usr/java/jdk1.8.0_66/lib/dt.jar -Dapplication.home=/usr/java/jdk1.8.0_66 -Xms8m

由于JVM展示的内容比较多,所以这里就省略了。我们可以从这里看到JVM的一些配置参数,并且可以看到JVM日志的输出路径,可以很方便的帮助我们定位问题。

3)接下来我们看下 jps -qjps -m

[email protected]:~$ jps -q
29474
27075
3875

[email protected]:~$ jps -m
29601 Jps -m
27075 BootStrap /workspace/test/SprintTest/conf/test.json
3875 App /workspace/test/LogTest/conf/test.json

可以看到,-q命令只展示进程号,而-m则是主方法的参数。

4)一般情况下,我们使用比较多的是jps -mlv参数;

5)获取元操服务器jps信息
jps命令是支持查看远程服务上的JVM进程信息的,但如果要查看其他机器上的JVM进程,需要在待查看机器上开启 jstatd 服务;

3. 原理

java程序在启动后,会在java.io.tmpdir指定的目录下,就是临时文件夹里,生成一个类似于hsperfdata_(userName)的文件夹(Linux中为/tmp/hsperfdata_{userName}/),该文件夹中有几个文件,名字就是java进程的pid;而jps命令列出当前运行的java进程,就是把这个目录里的文件名列一下而已。 至于系统的参数什么,可以通过解析这几个文件获得。

[email protected]:~$ cd /tmp/hsperfdata_deploy/
[email protected]:/tmp/hsperfdata_deploy$ ll
total 64
-rw------- 1 deploy deploy 32768 May 26 17:24 27075
-rw------- 1 deploy deploy 32768 May 26 17:24 3875

可以看到,进程号就是上面我们所展示的。

4.注意事项

注意,jps仅查找当前用户的Java进程,而不是当前系统中的所有进程,所以查询的时候需要注意用户的相关权限。

本文参考自(链接中包含了jps失效及更多有关jps的内容,大家都可以进行参考):
https://www.hollischuang.com/archives/105
Jps无法查看运行程序进程

二、jinfo命令

1. 介绍

  jinfo(Java Configuration Info),是Java自带的命令,用于实时查看和调整Java应用程序的配置参数,其中配置参数包含两部分,其中只能查看的是Java系统属性,既能查看又能调整的是JVM参数;并且,当系统崩溃时,jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息。

[email protected]:~$ jinfo -help
Usage:
    jinfo [option] 
        (to connect to running process)
    jinfo [option] 
        (to connect to a core file)
    jinfo [option] [server_id@]
        (to connect to remote debug server)

where 

我们来简单看下它的操作格式:

jinfo [option]                   进程id
jinfo [option]      生成core dump文件
jinfo [option] [server_id@] ...       连接远程机器操作

其中,参数option我们可以直接看上面的注释,比较简单,这里简单解释下:

[option]
           默认情况下,会展示全部的JVM参数和Java系统属性
-flag           查看对应名称的JVM参数
-flag [+|-]     对布尔类型的JVM配置进行开启或关闭 
-flag =  设置对应的JVM配置
-flags                展示全部JVM参数
-sysprops             展示Java系统属性
-h | -help            展示帮助信息
2. 使用

我们在服务器上进行简单操作下:
1)先看下最简单的方式,jinfo pid

[email protected]:~$ jinfo 20995
Attaching to process ID 20995, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.66-b17
Java System Properties:

com.sun.management.jmxremote.authenticate = false
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.66-b17
sun.boot.library.path = /usr/java/jdk1.8.0_66/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
java.rmi.server.randomIDs = true
file.encoding.pkg = sun.io
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
sun.os.patch.level = unknown
sun.java.launcher = SUN_STANDARD
user.country = US
...

VM Flags:
Non-default VM flags: -XX:CICompilerCount=4 -XX:CMSFullGCsBeforeCompaction=0 
-XX:CMSInitiatingOccupancyFraction=62 -XX:CMSTriggerRatio=70 
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=null 
-XX:InitialHeapSize=536870912 -XX:+ManagementServer 
-XX:MaxHeapSize=536870912 -XX:MaxMetaspaceSize=67108864 
...
Command line:  -Xms512m -Xmx512m -Xmn256m -XX:MaxMetaspaceSize=64m 
-XX:MetaspaceSize=64m -Dfile.encoding=UTF-8 -XX:+UseConcMarkSweepGC 
-XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection 
-XX:CMSFullGCsBeforeCompaction=0 -XX:CMSInitiatingOccupancyFraction=62 
-XX:CMSTriggerRatio=70 
...

这里展示的信息太多,省略了大部分数据;不过可以看到,展示的数据总体上是分两部分的,一部分是Java System Properties:,另一部分是VM Flags:

2)接下来我们看下 展示指定的JVM参数的值:

[email protected]:~$ jinfo -flag MaxNewSize 20995
-XX:MaxNewSize=268435456

3)JVM参数的调整,如果是布尔类型的,使用 jinfo -flag [+|-] PID,其中 + 表示开启,- 表示关闭操作;而如果是字符串或者数字类型,使用 jinfo -flag =,这里就不多演示了;

4)jinfo虽然可以在java程序运行时动态地修改JVM参数,但并不是所有的参数都支持动态修改,而哪些参数支持jinfo动态修改呢?在官方文档中有一段这样的描述:

Flags marked as manageable are dynamically writeable through the JDK management interface (com.sun.management.HotSpotDiagnosticMXBean API) and also through JConsole.

也就是说,通过com.sun.management.HotSpotDiagnosticMXBean 这个类的接口得到的参数,或者是标记为manageable的参数菜可以支持动态修改。首先,我们来看下标记为manageable的Flags,我们可以通过如下命令查看:

Linux环境: java -XX:+PrintFlagsInitial | grep manageable
Window环境:java -XX:+PrintFlagsInitial | findstr manageable

运行后获取到的数据如下:

[email protected]:~$ java -XX:+PrintFlagsInitial | grep manageable
     intx CMSAbortablePrecleanWaitMillis            = 100         {manageable}
     intx CMSTriggerInterval                        = -1          {manageable}
     intx CMSWaitDuration                           = 2000        {manageable}
     bool HeapDumpAfterFullGC                       = false       {manageable}
     bool HeapDumpBeforeFullGC                      = false       {manageable}
     bool HeapDumpOnOutOfMemoryError                = false       {manageable}
    ccstr HeapDumpPath                              =             {manageable}
    uintx MaxHeapFreeRatio                          = 70          {manageable}
    uintx MinHeapFreeRatio                          = 40          {manageable}
     bool PrintClassHistogram                       = false       {manageable}
     bool PrintClassHistogramAfterFullGC            = false       {manageable}
     bool PrintClassHistogramBeforeFullGC           = false       {manageable}
     bool PrintConcurrentLocks                      = false       {manageable}
     bool PrintGC                                   = false       {manageable}
     bool PrintGCDateStamps                         = false       {manageable}
     bool PrintGCDetails                            = false       {manageable}
     bool PrintGCID                                 = false       {manageable}
     bool PrintGCTimeStamps                         = false       {manageable}
[email protected]:~$

备注:为了展示,格式做了简单调整。

另外,我们也可以通过代码来实现,方式是通过 通过HotSpotDiagnosticMXBean API,查看该类的 Java Doc,有一个getDiagnosticOptions()这样的方法,该方法的详细描述如下:

Returns a list of VMOption objects for all diagnostic options. A diagnostic option is a writeable VM option that can be set dynamically mainly for troubleshooting and diagnosis.

接下来通过Java代码调用该API得到所有可动态修改的JVM参数, java代码如下:

/**
 * @author afei
 * @version 1.0.0
 * @since 2017年07月25日
 */
public class DiagnosticOptionsTest {
    public static void main(String[] args) {
        HotSpotDiagnostic mxBean = new HotSpotDiagnostic();
        List diagnosticVMOptions = mxBean.getDiagnosticOptions();
        for (VMOption vmOption:diagnosticVMOptions){
            System.out.println(vmOption.getName() + " = " + vmOption.getValue());
        }
    }
}

结果的话,大家跑一下程序就知道了,可以看到和Linux命令操作是一样的结果。
备注:由于HotSpotDiagnosticMXBean 是接口(public class HotSpotDiagnostic implements HotSpotDiagnosticMXBean ),所以需要通过它唯一的实现类HotSpotDiagnostic 来调用这个方法。

3. 总结

jinfo命令比较简单,使用该命令可以让我们在不重启JVM的情况下动态的修改JVM的参数,这点对我们来说有时候有些时候还是挺有用的。

本文最后部分来自阿飞哥的博客,博客地址:
阿飞的博客 - - jinfo命令详解

你可能感兴趣的:((二)Java基础工具学习)