我的世界java版指令,我的世界java指令全套
目录:
一.引言
二.基础故障处理工具
2.1 概述
2.2. jps:虚拟机进程状况工具
2.3. jstat:虚拟机统计信息监视工具
2.3. jinfo:java配置信息工具
2.5. jmap:Java内存映像工具
2.7. jstack:Java堆栈跟踪工具
2.8. 基础工具总结
三. 可视化故障处理工具
3.1. JHSDB:基于服务性DL的调试工具
3.2. JConsole:Java监视与管理控制台
3.3. JVisualVM:多合一故障处理工具
3.4. Java Mission Control(JMC):可持续在线的监控工具
四. HotSpot虚拟机插件及工具
一.引言
给一个系统定位问题的时候,知识、经验是关键基础,数据是依据,工具是运用知识处理数据的手段。
异常堆栈、虚拟机运行日志、垃圾收集器日志、线程快照(threaddump/javacore文件)、堆转储快照(heapdump/hprof文件)。
工具永远都是知识技能的一层包装,没有什么工具是“秘密武器”,拥有了就能“包治百病”。
二.基础故障处理工具2.1 概述
选择采用Java语言本身来实现这些故障处理工具
当应用程序部署到生产环境后,无论是人工物理接触到服务器还是远程Telnet到服务器上都可能会受到限制。
借助这些工具类库里面的接口和实现代码,开发者可以选择直接在应用程序中提供功能强大的监控分析功能。
启用 JMX 功能
JDK5或以下版本,在程序启动时请添加参数“-Dcom.sun.management.jmxremote”开启JMX管理功能。
JDK6或以上版本,默认开启了JMX管理。
2.2. jps:虚拟机进程状况工具
JDK的很多小工具的名字都参考了UNIX命令的命名方式,jps(JVM Process Status Tool)是其中的典型。除了名字像UNIX的ps命令之外,它的功能也和ps命令类似:可以列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(LVMID,Local Virtual Machine Identifier)。虽然功能比较单一,但它绝对是使用频率最高的JDK 命令行工具,因为其他的JDK工具大多需要输入它查询到的LVMID来确定要监控的是哪一个虚拟机进程。对于本地虚拟机进程来说,LVMID与操作系统的进程ID(PID,Process Identifier)是一致的,使用Windows的任务管理器或者UNIX的ps命令也可以查询到虚拟机进程的LVMID,但如果同时启动了多个虚拟机进程,无法根据进程名称定位时,那就必须依赖jps命令显示主类的功能才能区分了。
jps命令格式:
jps [ options ] [ hostid ]
jps可以通过RMI协议开启了RMI服务的远程虚拟机进程状态,hostid为RMI注册表中注册的主机名。
jps常用的option选项:
选项
作用
-q
只输出LVMID
-m
输出虚拟机进程启动时传递给主类main()函数的参数
-l
输出主类全名,如果进程执行的事jar包,输出jar路径
-v
输出虚拟机进程启动时JVM参数
案例
public class Jstat { /** * vm参数为 -Xms30m -Xmx30m -Xmn10m * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { Thread.sleep(1000000); }}
运行之后,使用jps命令,将会展示虚拟机进程id和名字:
显示所有大图
2.3. jinfo:Java配置信息工具
jstat是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾回收、JIT编译等运行数据,在没有GUI图形界面,只是提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
jstat的命令格式:
jstat [option vmid [interval [s|ms] [count]] ]
1. option: 参数选项
2. -t: 可以在打印的列加上Timestamp列,用于显示系统运行的时间
3. -h: 可以在周期性数据数据的时候,可以在指定输出多少行以后输出一次表头
4. vmid: Virtual Machine ID( 进程的 pid)
5. interval: 执行每次的间隔时间,单位为毫秒
6. count: 用于指定输出多少次记录,缺省则会一直打印
7. 对于命令格式中的VMID和LVMID,如过是本地虚拟机进程,VMID和LVMID是一致的,如 果是远程虚拟机,那VMID的格式应当是:[protocol:] [//] lvmid[@hostname[:port]/servername]
8. 参数interval 和count分别表示查询的间隔和次数,如果省略这两个参数,说明只查询一次。
Jstat常用option选项:
选项
作用
-class
类装载数量、卸载数量、总空间以及类状态所消耗时间
-GC
监视Java堆容量状况,包括Eden、Survivor、老年代、永久代等
-GCcapacity
监视Java堆最大、最小空间
-GCutil
关注已使用空间占总空间的百分比
-GCcause
类似GCutil,额外输出上次GC的原因
-GCnew
新生代GC状况
-GCnewcapacity
与-GCnew类似,输出主要关注使用到的最大、最小空间
-GCold
老年代GC状况
-GColdcapacity
与-GCold类似,输出主要关注使用到的最大、最小空间
-GCpermcapacity
输出永久代使用到的最大、最小空间
-compiler
输出JIT编译过的方法和耗时
-printcompilation
输出已经被JIT编译的方法
-GCmetacapacity
元数据空间统计
案例
加上-GC显示将会GC堆信息,使用上一个案例,设置VM参数为 -Xms30m -Xmx30m -Xmn10m ,即初始内存30m,最大内存30m,年轻代10m。
运行程序,使用 jstat -gc 6128 命令结果如下,可以看到GC堆信息:
S0C:年轻代中第一个Survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个Survivor(幸存区)的容量 (字节)
S0U :年轻代中第一个Survivor(幸存区)目前已使用空间 (字节)
S1U :年轻代中第二个Survivor(幸存区)目前已使用空间 (字节)
EC :年轻代中Eden(伊甸园)的容量 (字节)
EU :年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC :Old代的容量 (字节)
OU :Old代目前已使用空间 (字节)
MC:metaspace(元空间)的容量 (字节)
MU:metaspace(元空间)目前已使用空间 (字节)
YGC :从应用程序启动到采样时年轻代中GC次数
YGCT :从应用程序启动到采样时年轻代中GC所用时间(s)
FGC :从应用程序启动到采样时old代(全GC)GC次数
FGCT :从应用程序启动到采样时old代(全GC)GC所用时间(s)
GCT:从应用程序启动到采样时GC用的总时间(s)
从图中可以看出,各项结果符合我们的VM参数设置的信息。
2.5. jmap:Java内存映像工具
jmap命令用于生成堆转储快照。jmap的作用并不仅仅为了获取dump文件,它还可以查询finalize执行队列、java堆和永久代的详细信息。如空间使用率、当前用的是哪种收集器等。
jmap格式:
jmap [option] vmid
jmap常用option选项:
选项
作用
-dump
生成堆转储快照,格式为-dump:[live,]format=b,file=,不建议使用
-finalizerinfo
显示在F-Queue中等待Finalizer线程执行finalize方法的对象
-heap
显示java堆详细信息,回收器种类、参数配置、分代状况等
-histo
显示堆中对象统计信息,包括类、实例数量、合计容量,会先触发GC,再统计信息,不建议使用
-permstat
查看永久代内存状态,比较耗时,会暂停应用,不建议使用
案例:
还是上面的例子。
使用jmap -heap 6128,可以看到我们的VM参数设置的信息:
生成dump文件
jmap -dump:live,format=b,file=C:UserslxDesktop est1.bin 9472
将生成堆转储快照,这里我生成到桌面。后面可以使用jhat分析dump文件。
2.7. jstack:Java堆栈跟踪工具
jstack命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程死锁、死循环、请求外部资源导致长时间等待等。
jstack 格式:
jstack [option] vmid
jstack常见option选项:
选项
作用
案例
-m
如果调用本地方法,则显示C/C++的堆栈
jstack -m 1479
-l
除堆栈外,显示关于锁的附加信息
jstack -l 1479
-F
当正常输出的请求不被响应时,强制输出线程堆栈
jstack -F 1479
案例
jstack -l 9472
会输出很多信息,我们可以找到如下信息:
可以看到,main线程正在限时等待——因为sleep的原因。
jstack 可以帮助我们用来分析线程信息,比如死锁,状态等。
2.8. 基础工具总结jps将打印所有正在运行的 Java 进程。jstat允许用户查看目标 Java 进程的类加载、即时编译以及垃圾回收相关的信息。它常用于检测垃圾回收问题以及内存泄漏问题。jmap允许用户统计目标 Java 进程的堆中存放的 Java 对象,并将它们导出成二进制文件。jinfo将打印目标 Java 进程的配置参数,并能够改动其中 manageabe 的参数。jstack将打印目标 Java 进程中各个线程的栈轨迹、线程状态、锁状况等信息。它还将自动检测死锁。三. 可视化故障处理工具3.1. JHSDB:基于服务性DL的调试工具
HSDB(Hotspot debugger),是一款内置于 SA 中的 GUI 调试工具,可用于调试 JVM 运行时数据,从而进行故障排除。
3.1.1 HSDB发展
sa-jdi.jar
在 Java9 之前,JAVA_HOME/lib 目录下有个 sa-jdi.jar,可以通过如下命令启动HSDB(图形界面)及CLHSDB(命令行)。
java -cp /Library/Java/JavaVirtualMachines/jdk1.8.0_301.jdk/Contents/Home/lib/sa-jdi.jar sun.jvm.hotspot.HSDB
sa-jdi.jar中的sa的全称为 Serviceability Agent,它之前是sun公司提供的一个用于协助调试 HotSpot 的组件,而 HSDB 便是使用Serviceability Agent 来实现的。
由于Serviceability Agent 在使用的时候会先attach进程,然后暂停进程进行snapshot,最后deattach进程(进程恢复运行),所以在使用 HSDB 时要注意。
jhsdb
jhsdb 是 Java9 引入的,可以在 JAVA_HOME/bin 目录下找到 jhsdb;它取代了 JDK9 之前的 JAVA_HOME/lib/sa-jdi.jar,可以通过下述命令来启动 HSDB。
$ cd /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home/bin/$ jhsdb hsdb
jhsdb 有 clhsdb、debugd、hsdb、jstack、jmap、jinfo、jsnap 这些 mode 可以使用。
其中 hsdb 为 ui debugger,就是 jdk9 之前的 sun.jvm.hotspot.HSDB;而 clhsdb 即为 jdk9 之前的sun.jvm.hotspot.CLHSDB。
3.1.2 HSDB实操3.1.2.1 启动HSDB
检测不同 JDK 版本需要使用不同的 HSDB 版本,否则容易出现无法扫描到对象等莫名其妙的问题。
Mac:JDK7 和 JDK8 均可以采用以下的方式
$ java -cp /Library/Java/JavaVirtualMachines/jdk1.8.0_301.jdk/Contents/Home/lib/sa-jdi.jar sun.jvm.hotspot.HSDB
如果执行报错,则前面加上 sudo,或者更改 sa-jdi.jar 的权限。
sudo chmod -R 777 sa-jdi.jar
本地安装的是 JDK8,在启动 HSDB 后,发现无法连接到 Java 进程,在 attach 过程中会提示如下错误:
网上搜索相关解决方案,建议更换 JDK 版本。可以去参考 Mac下安装多个版本的JDK并随意切换
个人在配置的过程中遇到了这样一个问题:在切换 JDK 版本时,发现不生效,网上各种查找方案,动手尝试,最后都没有成功。解决方案:手动修改 .bash_profile 文件,增加注释。
首次尝试 JDK 11,但是还是无法 attach Java 进程,试了好久都不行,只能再次尝试 JDK9.
而 JDK9 的启动方式有些区别
$ cd /Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home/bin/$ jhsdb hsdb
其中启动版本可以使用 /usr/libexec/java_home -V 获取 HSDB 对 Serial GC 支持的较好,因此 Debug 时增加参数 -XX:+UseSerialGC。注意运行程序 Java 的版本和 hsdb 的 Java 版本要一致才行。
注意:如果后续想要下载 .class 文件,启动 hsdb 时,需要执行 sudo jhsdb hsdb 命令。
3.1.2.2 HSDB可视化界面
比如说有这么一个 Java 程序,我们使用 Thread.sleep 方法让其长久等待,然后获取其进程 id。
public class InvokeTest { public static void printException(int num) { new Exception("#" + num).printStackTrace(); } public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InterruptedException { Class<?> cl = Class.forName("InvokeTest"); Method method = cl.getMethod("printException", int.class); for (int i = 1; i < 20; i++) { method.invoke(null, i); if (i == 17) { Thread.sleep(Integer.MAX_VALUE); } } }}
然后在 terminal 窗口执行 jps 命令:
27995 InvokeTest
然后在 HSDB 界面点击 file 的 attach,输入 pid,如果按照上述步骤操作,是可以操作成功的。
attach 成功后,效果如下所示:
更多操作选择推荐阅读:解读HSDB
3.1.2.3分析对象存储区域
下面代码中的 heatStatic、heat、heatWay 分别存储在什么地方呢?
package com.msdn.java.hotspot.hsdb;public class Heat2 { private static Heat heatStatic = new Heat(); private Heat heat = new Heat(); public void generate() { Heat heatWay = new Heat(); System.out.println("way way"); }}class Heat{ }
测试类
package com.msdn.java.hotspot.hsdb;public class HeatTest { public static void main(String[] args) { Heat2 heat2 = new Heat2(); heat2.generate(); }}
关于上述问题,我们大概都知道该怎么回答:
heatStatic 属于静态变量,引用应该是放在方法区中,对象实例位于堆中;
heat 属于成员变量,在堆上,作为 Heat2 对象实例的属性字段;
heatWay 属于局部变量,位于 Java 线程的调用栈上。
那么如何来看看这些变量在 JVM 中是怎么存储的?这里借助 HSDB 工具来进行演示。
此处我们使用 IDEA 进行断点调试,后续会再介绍 JDB 如何进行代码调试。
IDEA 执行前需要增加 JVM 参数配置,HSDB 对 Serial GC 支持的较好,因此 Debug 时增加参数 -XX:+UseSerialGC;此外设置 Java Heap 为 10MB;UseCompressedOops 参数用来压缩 64位指针,节省内存空间。关于该参数的详细介绍,推荐阅读本文。
最终 JVM 参数配置如下:
-XX:+UseSerialGC -Xmn10M -XX:-UseCompressedOops
然后在 Heat2 中的 System 语句处打上断点,开始 debug 执行上述代码。
接着打开命令行窗口执行 jps 命令查看我们要调试的 Java 进程的 pid 是多少:
% jps9977 HeatTest
接着我们按照上文讲解启动 HSDB,注意在 IDEA 中执行代码时,Java 版本为 Java9,要与 HSDB 相关的 Java 版本一致。
在 attach 成功后,选中 main线程并打开其栈信息,接着打开 console 窗口,下面我将自测的命令及结果都列举了出来,并简要介绍其作用,以及可能遇到的问题。
首先执行 help 命令,查看所有可用的命令
hsdb> helpAvailable commands: assert true | false attach pid | exec core buildreplayjars [ all | app | boot ] | [ prefix ] detach dis address [length] disassemble address dumpcfg { -a | id } dumpcodecache dumpideal { -a | id } dumpilt { -a | id } dumpreplaydata { <address > | -a | <thread_id> } echo [ true | false ] examine [ address/count ] | [ address,address] field [ type [ name fieldtype isStatic offset address ] ] findpc address flags [ flag | -nd ] help [ command ] history inspect expression intConstant [ name [ value ] ] jdis address jhisto jstack [-v] livenmethods longConstant [ name [ value ] ] pmap print expression printall printas type expression printmdo [ -a | expression ] printstatics [ type ] pstack [-v] quit reattach revptrs address scanoops start end [ type ] search [ heap | perm | rawheap | codecache | threads ] value source filename symbol address symboldump symboltable name thread { -a | id } threads tokenize … type [ type [ name super isOop isInteger isUnsigned size ] ] universe verbose true | false versioncheck [ true | false ] vmstructsdump where { -a | id } hsdb> where 3587Thread 3587 Address: 0x00007fb25c00a800Java Stack Trace for mainThread state = BLOCKED – public void generate() @0x0000000116953ff8 @bci = 8, line = 15, pc = 0x0000000123cdacd7, oop = 0x000000013316f128 (Interpreted) – public static void main(java.lang.String[]) @0x00000001169539b0 @bci = 9, line = 11, pc = 0x0000000123caf4ba (Interpreted)hsdb>
3.1.2.4 主要命令简介
命令1、universe 命令来查看GC堆的地址范围和使用情况,可以看到我们创建的三个对象都是在 eden 区。因为使用的是 Java9,所以已经不存在 Perm gen 区了,
hsdb> universeHeap Parameters:Gen 0: eden [0x0000000132e00000,0x000000013318c970,0x0000000133600000) space capacity = 8388608, 44.36473846435547 used from [0x0000000133600000,0x0000000133600000,0x0000000133700000) space capacity = 1048576, 0.0 used to [0x0000000133700000,0x0000000133700000,0x0000000133800000) space capacity = 1048576, 0.0 usedInvocations: 0Gen 1: old [0x0000000133800000,0x0000000133800000,0x0000000142e00000) space capacity = 257949696, 0.0 usedInvocations: 0
不借助命令的话,还可以这样操作来查看。
命令2、scanoops 查看类型
Java 代码里,执行到 System 输出语句时应该创建了3个 Heat 的实例,它们必然在 GC 堆里,但都在哪里,可以用scanoops命令来看:
hsdb> scanoops 0x0000000132e00000 0x000000013318c970 com.msdn.java.hotspot.hsdb.Heat0x000000013316f118 com/msdn/java/hotspot/hsdb/Heat0x000000013316f140 com/msdn/java/hotspot/hsdb/Heat0x000000013316f150 com/msdn/java/hotspot/hsdb/Heat
scanoops 接受两个必选参数和一个可选参数:必选参数是要扫描的地址范围,一个是起始地址一个是结束地址;可选参数用于指定要扫描什么类型的对象实例。实际扫描的时候会扫出指定的类型及其派生类的实例。
从 universe 命令返回结果可知,对象是在 eden 里分配的内存(注意used),所以执行 scanoops 命令时地址范围可以从 eden 中获取。
本文地址:https://www.cknow.cn/archives/715
以上内容源自互联网,由百科助手整理汇总,其目的在于收集传播生活技巧,行业技能,本网站不对其真实性、可靠性承担任何法律责任。特此声明!
如发现本站文章存在版权问题,烦请提供版权疑问、侵权链接、联系方式等信息发邮件至candieraddenipc92@gmail.com,我们将及时沟通与处理。