jinfo:JAVA进程运行时修改虚拟机参数利器(无需重启)

f627 9年前

     注:本文翻译自JAVA极客上面的一片文章,有些地方直译,莫介意。

      虚拟机总会有出现问题的时候,并且你深深的知道如果通过配置一些参数使得虚拟机打印一些运行时信息,可以通过这种途径改善虚拟机的运行状况。如 XX:+HeapDumpOnOutOfMemoryError和XX:+PrintGCDetails。但是有时候这些参数会丢失,这是件令人头痛的事情。
       因此,你痛苦的耸了耸肩,杀掉虚拟机进程,修改启动参数并祈祷之前的糟糕状况可以在重新启动之后重现。现在你拥有足够的证据来查找问题的根源,并改正。前面描述的方式,很显然需要一次额外的重启并添加一些调试参数。实际上,不需要重启虚拟机的方法是有的,这种方法好处是大大的。
      JDK打包工具里面为我们提供了一个很好的小工具。jinfo是一个命令行工具,通过这个工具可以获取JAVA进程运行时的一些信息,通过使用jinfo 和一些参数,可以动态修改JAVA进程的虚拟机参数,这些参数并不是万能的,但是在一些场景中是非常有用的。虚拟机的这些参数可以通过下面的命令查看:
     [tomcat@centos86 ~]$ java -XX:+PrintFlagsFinal -version | grep manageable       intx CMSAbortablePrecleanWaitMillis            = 100             {manageable}                intx CMSWaitDuration                           = 2000            {manageable}                bool HeapDumpAfterFullGC                       = false           {manageable}                bool HeapDumpBeforeFullGC                      = false           {manageable}                bool HeapDumpOnOutOfMemoryError                = false           {manageable}               ccstr HeapDumpPath                              =                 {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 PrintGCTimeStamps                         = false           {manageable} 
</div>
     
          我们通过-XX:+PrintFlagsFinal -version参数可以获取JVM的所有选项,然而manageable才是我们所感兴趣的,通过JDK的管理接口(com.sun.management.HotSpotDiagnosticMCBean API)可以动态写入。非常相似的MBean也可以通过Jconsole查看,对于我来说命令行的方式是非常方便的。 
    下面是一个使用jinfo的例子: 
    我们通过动态打开JVM的GC日志开关例子来演示jinfo如何使用。 
    我们先通过jps来查看当前运行状态的虚拟机进程:
[tomcat@centos86 ~]$ jps   10463 Bootstrap   32588 Bootstrap   27250 Bootstrap 
    我们通过使用jinfo来打开虚拟机GC日志打印参数,-XX:+PrintGC和-XX:+PrintGCDetails。使用命令行方式微小的差别在于需要为jinfo同时指定-XX:+PrintGC和-XX:+PrintGCDetails参数。除了通过启动脚本可以设置参数,PrintGC默认是打开的,因此我们只需要打开PrintGCDetails参数。
</div>
jinfo -flag +PrintGC 27250   jinfo -flag +PrintGCDDetails 27250 
结果是这样的:
[GC [PSYoungGen: 147073K->16612K(145920K)] 453287K->322827K(495616K), 0.0429920 secs] [Times: user=0.08 sys=0.00, real=0.04 secs]    [GC [PSYoungGen: 145636K->25582K(150528K)] 451851K->333586K(500224K), 0.0461510 secs] [Times: user=0.11 sys=0.00, real=0.05 secs]    [GC [PSYoungGen: 150510K->29667K(154624K)] 458514K->351748K(504320K), 0.1074310 secs] [Times: user=0.31 sys=0.00, real=0.11 secs]    [GC [PSYoungGen: 154595K->14379K(181248K)] 476676K->336851K(530944K), 0.0738610 secs] [Times: user=0.09 sys=0.02, real=0.08 secs]    [GC [PSYoungGen: 160811K->16390K(183808K)] 483283K->338991K(533504K), 0.0363680 secs] [Times: user=0.10 sys=0.00, real=0.03 secs]    [GC [PSYoungGen: 162822K->17194K(199680K)] 485423K->339987K(549376K), 0.1190460 secs] [Times: user=0.28 sys=0.10, real=0.12 secs]    [GC [PSYoungGen: 186666K->15663K(203264K)] 509459K->338613K(552960K), 0.0550360 secs] [Times: user=0.11 sys=0.07, real=0.06 secs]  

</div>
如果需要关闭GC日志的打印,使用下面的命令:
jinfo -flag -PrintGC 27250   jinfo -flag -PrintGCDDetails 27250
来自