我的世界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,我们将及时沟通与处理。