# 02-jdk-bin下相关工具
# 一、基本工具
javac.exe -- Java语言编译器
java.exe -- Java应用程序启动器,JDK 1.6版里同时用于开发和部署,旧的部署启动器,jre,不在提供
javadoc.exe -- Java API 文档生成器
apt.exe -- java 注释处理器
appletviewer.exe -- java applet 小程序查看器
jar.exe -- java文件压缩打包工具
jdb.exe -- Java 调试器.
javah.exe -- C 头文件和stub生成器,用于写本地化方法,例如生产JNI样式的头文件
javap.exe -- class文件 反编译工具
extcheck.exe -- 用于检测jar包中的问题
C:\Users\dong>jar --help
用法: jar [OPTION...] [ [--release VERSION] [-C dir] files] ...
jar 创建类和资源的档案, 并且可以处理档案中的单个类或资源或者从档案中还原单个类或资源。
示例:
# 创建包含两个类文件的名为 classes.jar 的档案:
jar --create --file classes.jar Foo.class Bar.class
# 使用现有的清单创建档案, 其中包含 foo/ 中的所有文件:
jar --create --file classes.jar --manifest mymanifest -C foo/ .
# 创建模块化 jar 档案, 其中模块描述符位于
# classes/module-info.class:
jar --create --file foo.jar --main-class com.foo.Main --module-version 1.0 -C foo/ classes resources
# 将现有的非模块化 jar 更新为模块化 jar:
jar --update --file foo.jar --main-class com.foo.Main --module-version 1.0 -C foo/ module-info.class
# 创建包含多个发行版的 jar, 并将一些文件放在 META-INF/versions/9 目录中:
jar --create --file mr.jar -C foo classes --release 9 -C foo9 classes
要缩短或简化 jar 命令, 可以在单独的文本文件中指定参数,
并使用 @ 符号作为前缀将此文件传递给 jar 命令。
示例:
# 从文件 classes.list 读取附加选项和类文件列表
jar --create --file my.jar @classes.list
主操作模式:
-c, --create 创建档案
-i, --generate-index=FILE 为指定的 jar 档案生成索引信息
-t, --list 列出档案的目录
-u, --update 更新现有 jar 档案
-x, --extract 从档案中提取指定的 (或全部) 文件
-d, --describe-module 输出模块描述符或自动模块名称
在任意模式下有效的操作修饰符:
-C DIR 更改为指定的目录并包含以下文件
-f, --file=FILE 档案文件名。省略时, 基于操作使用 stdin 或 stdout
--release VERSION 将下面的所有文件都放在jar 的版本化目录中 (即 META-INF/versions/VERSION/)
-v, --verbose 在标准输出中生成详细输出
在创建和更新模式下有效的操作修饰符:
-e, --main-class=CLASSNAME 捆绑到模块化或可执行jar 档案的独立应用程序的应用程序入口点
-m, --manifest=FILE 包含指定清单文件中的清单信息
-M, --no-manifest 不为条目创建清单文件
--module-version=VERSION 创建模块化 jar 或更新非模块化 jar 时的模块版本
--hash-modules=PATTERN 计算和记录模块的散列,这些模块按指定模式匹配并直接或间接依赖于所创建的模块化 jar 或所更新的非模块化 jar
-p, --module-path 模块被依赖对象的位置, 用于生成散列
只在创建, 更新和生成索引模式下有效的操作修饰符:
-0, --no-compress 仅存储; 不使用 ZIP 压缩
其他选项:
-?, -h, --help[:compat] 提供此帮助,也可以选择性地提供兼容性帮助
--help-extra 提供额外选项的帮助
--version 输出程序版本
如果模块描述符 'module-info.class' 位于指定目录的
根目录中, 或者位于 jar 档案本身的根目录中, 则
该档案是一个模块化 jar。以下操作只在创建模块化 jar,
或更新现有的非模块化 jar 时有效: '--module-version',
'--hash-modules' 和 '--module-path'。
如果为长选项提供了必需参数或可选参数, 则它们对于
任何对应的短选项也是必需或可选的。
C:\Users\dong>javac
用法: javac <options> <source files>
其中, 可能的选项包括:
@<filename> 从文件读取选项和文件名
-Akey[=value] 传递给注释处理程序的选项
--add-modules <模块>(,<模块>)* 除了初始模块之外要解析的根模块; 如果 <module> 为 ALL-MODULE-PATH, 则为模块路径中的所有模块。
--boot-class-path <path>, -bootclasspath <path> 覆盖引导类文件的位置
--class-path <path>, -classpath <path>, -cp <path> 指定查找用户类文件和注释处理程序的位置
-d <directory> 指定放置生成的类文件的位置
-deprecation 输出使用已过时的 API 的源位置
--enable-preview 启用预览语言功能。要与 -source 或 --release 一起使用。
-encoding <encoding> 指定源文件使用的字符编码
-endorseddirs <dirs> 覆盖签名的标准路径的位置
-extdirs <dirs> 覆盖所安装扩展的位置
-g 生成所有调试信息
-g:{lines,vars,source} 只生成某些调试信息
-g:none 不生成任何调试信息
-h <directory> 指定放置生成的本机标头文件的位置
--help, -help, -? 输出此帮助消息
--help-extra, -X 输出额外选项的帮助
-implicit:{none,class} 指定是否为隐式引用文件生成类文件
-J<flag> 直接将 <标记> 传递给运行时系统
--limit-modules <模块>(,<模块>)* 限制可观察模块的领域
--module <module-name>, -m <module-name> 只编译指定的模块, 请检查时间戳
--module-path <path>, -p <path> 指定查找应用程序模块的位置
--module-source-path <module-source-path> 指定查找多个模块的输入源文件的位置
--module-version <版本> 指定正在编译的模块版本
-nowarn 不生成任何警告
-parameters 生成元数据以用于方法参数的反射
-proc:{none,only} 控制是否执行注释处理和/或编译。
-processor <class1>[,<class2>,<class3>...] 要运行的注释处理程序的名称; 绕过默认的搜索进程
--processor-module-path <path> 指定查找注释处理程序的模块路径
--processor-path <path>, -processorpath <path> 指定查找注释处理程序的位置
-profile <profile> 请确保使用的 API 在指定的配置文件中可用
--release <release> 针对特定 VM 版本进行编译。支持的目标: 6, 7, 8, 9, 10, 11
-s <directory> 指定放置生成的源文件的位置
-source <release> 提供与指定发行版的源兼容性
--source-path <path>, -sourcepath <path> 指定查找输入源文件的位置
--system <jdk>|none 覆盖系统模块位置
-target <release> 生成特定 VM 版本的类文件
--upgrade-module-path <path> 覆盖可升级模块位置
-verbose 输出有关编译器正在执行的操作的消息
--version, -version 版本信息
-Werror 出现警告时终止编译
# 二、监控应用
# 1、jps.exe
JVM Process Status 进程状态工具,列出目标系统的HotSpot JJVM
# 2、jstat JVM性能监控
JDK自带的一个轻量级小工具,全称“Java Virtual Machine statistics monitoring tool”,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。
C:\Users\dong>jstat
Usage: jstat --help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
Definitions:
<option> An option reported by the -options option
<vmid> Virtual Machine Identifier. A vmid takes the following form:
<lvmid>[@<hostname>[:<port>]]
Where <lvmid> is the local vm identifier for the target
Java virtual machine, typically a process id; <hostname> is
the name of the host running the target Java virtual machine;
and <port> is the port number for the rmiregistry on the
target host. See the jvmstat documentation for a more complete
description of the Virtual Machine Identifier.
<lines> Number of samples between header lines.
<interval> Sampling interval. The following forms are allowed:
<n>["ms"|"s"]
Where <n> is an integer and the suffix specifies the units as
milliseconds("ms") or seconds("s"). The default units are "ms".
<count> Number of samples to take before terminating.
-J<flag> Pass <flag> directly to the runtime system.
-? -h --help Prints this help message.
-help Prints this help message.
其中options支持:
C:\Users\dong>jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
# 3、jstatd.exe JVM jstat 的守护进程
# 4、jhat 堆储存查看器
jhat是一个Java heap dump文件浏览器。这个工具分析Java堆复制文件(例如,由上面的 "jmap -dump"所产生的)。Jhat启动一个允许堆中的对象在web浏览器中进行分析的web服务器。这个工具并不是想用于应用系统中而是用于"离线"分 析。“jhat工具是平HIDDEN立的”,其意思是,它可以被用来观察在任何平台上所产生的堆复制。例如,我们有可能在Linux系统上使用jhat来 观察一个在Solaris OS上所产生的堆复制
# 5、jmap Java内存图
主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。
jmap命令可以获得运行中的jvm的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等。可以使用jmap生成Heap Dump。
注意:这里的堆是指java进程中的堆,不单单是
# 6、jstack Java堆栈跟踪
# 7、jvisualvm (gui监控工具)
JVM监测、故障排除、分析工具,主要以图形化界面的方式提供运行于指定虚拟机的Java应用程序的详细信息,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的).
# 8、jconsole(gui监控工具)
主要用于监测并显示运行于Java平台上的应用程序的性能和资源占用等信息
# 9、jmc(gui工具)
Java任务控制工具(Java Mission Control),主要用于HotSpot JVM的生产时间监测、分析、诊断,数据比jvisualvm数据更加丰富
# 三、安全相关的
# 1、policytool:gui工具
# 2、keytool:密钥工具
# 3、kinit,klist,ktab:kerberos管理工具
# 4、jarsigner:签名,签名校验工具
# 四、案列
# 一、一行代码 引发的FULL GC
# 1.问题描述
**2021年1月27日运维同事发现线上出生证明服务CPU使用报警,经排查后发下系统一直在FULL GC **
查看服务器gc命令: jstat -gcutil 进程号 时间间隔
前提是 执行命令的用户权限 >= 启动java进程用户的权限
**同时CPU使用率较高 **
**同时线上服务器响应时间变长 **
**经确认线下没有大规模的活动,没有异常流量进入,排除业务和流量问题后项目组开始排查系统问题 **
# 2.问题定位
**系统频繁的FULL GC明显不正常,开始排查是否存在内存泄露的情况 **
# 1)dump java进程内存
使用命令
jmap -dump:live,format=b,file=heap-dump.bin 进程号
将java进程内存快照到问题内,通过堡垒机将内存文件下载到本地
# 2)使用MAT对内存进行分析
MAT的解释以及用法请参考: https://juejin.cn/post/6844903782766084103
没有MAT工具的同学可以百度搜索:“MAT”,进入官网下载即可
打开MAT后将下载好的文件导入到MAT内
导入后发现内存中大对象占比非常大,初步定为存在内存泄露的情况
点击 “Leak Suspects (内存泄漏的工具)” 进入内存泄露分析页面
进入后发现“PoolingHttpClientConnectionManager”对象实例非常多,内存占用率也达到了96.6%
点击“Details”进入详情页面,同时将滚动条拉倒最下,检查线程调用栈信息,发现是阿里云OSS客户端 存在内存泄露
排查代码是否有使用阿里云OSS客户端,经排查后发现在调用图片上传接口时 “没有关闭客户端连接”