JDK工具详解之(2)
一.jVisualVm
jdk9及以上自带visualVM,需要手动安装,下载地址VisualVm。下载后修改etc/visualvm.conf文件,配置jdk路径即可
1.1安装Visual GC
Java VisualVM默认没有安装Visual GC插件,需要手动安装,JDK的安装目录的bin目露下双击jvisualvm.exe,即可打开Java VisualVM,点击菜单栏 工具->插件 安装Visual GC.
安装完成后重启Java VisualVM,Visual GC界面自动打开,即可看到查看本地JVM中堆内存的分代情况
1.2监控页面
1.2.线程界面
1.3 sampler 界面
除了sampler 还有一个profiler 界面,两个界面类似
可点击cpu 分析cpu ,也可点击Memory 分析内存
1.4 jVisualVm 查看 jmap转储的bin文件
二.jhat
Java Virtual Machine Heap Analysis Tool 虚拟机堆转储快照分析工具,用于分析heapdump文件,它会建立一个HTTP/HTML服务器,让用户可以在浏览器上查看分析结果,可以查找诸如内存方面的问题。不过jhat和MAT比较起来,就没有MAT那么直观了,MAT是以图形界面的方式展现结果
2.1参数
- -J< flag >
因为 jhat 命令实际上会启动一个JVM来执行, 通过 -J 可以在启动JVM时传入一些启动参数. 例如, -J-Xmx512m 则指定运行 jhat 的Java虚拟机使用的最大堆内存为 512 MB. 如果需要使用多个JVM启动参数,则传入多个 -Jxxxxxx. - -stack false|true
关闭对象分配调用栈跟踪(tracking object allocation call stack)。 如果分配位置信息在堆转储中不可用. 则必须将此标志设置为 false. 默认值为 true. - -refs false|true
关闭对象引用跟踪(tracking of references to objects)。 默认值为 true. 默认情况下, 返回的指针是指向其他特定对象的对象,如反向链接或输入引用(referrers or incoming references), 会统计/计算堆中的所有对象。 - -port port-number
设置 jhat HTTP server 的端口号. 默认值 7000。 - -exclude exclude-file
指定对象查询时需要排除的数据成员列表文件(a file that lists data members that should be excluded from the reachable objects query)。 例如, 如果文件列列出了 java.lang.String.value , 那么当从某个特定对象 Object o 计算可达的对象列表时, 引用路径涉及 java.lang.String.value 的都会被排除。 - -baseline exclude-file
指定一个基准堆转储(baseline heap dump)。 在两个 heap dumps 中有相同 object ID 的对象会被标记为不是新的(marked as not being new). 其他对象被标记为新的(new). 在比较两个不同的堆转储时很有用。 - -debug int
设置 debug 级别. 0 表示不输出调试信息。 值越大则表示输出更详细的 debug 信息。 - -version
启动后只显示版本信息就退出。
2.2、jhat中重点内容关注
1.通过jmap 生成堆文件
jmap -dump:live,file=heap.bin 15703
2.使用jhat 命令启动根据堆文件产生的jvm http 服务
jhat heap.bin
3.查看html信息
查看jhat展示的网页信息中,一般查看堆异常情况主要看这个两个部分: Show instance counts for all classes (excluding platform),平台外的所有对象信息。Show heap histogram 以树状图形式展示堆情况。
这两部分内容在首页的http://ip:7000页面的最下面中的Other Queries里的两个链接中进入。
- 显示出堆中所包含的所有的类
- 从根集能引用到的对象
- 显示平台包括的所有类的实例数量
- 显示平台外的所有对象信息
- 堆实例的分布表(堆直方图)
- 展示正在结束的统计
- 执行对象查询语句 描述如何在jhat查询
三.jdb (The Java Debugger)
现在大多数的java debug 都是借由IDE 进行调试,但是有时候现场情况不允许使用IDE 进行调试
所以可以使用java本身自带的jdb来进行调试工作,相比与IDE 来说,jdb 比较难用。但是可以简单了解一下,避免出现不能使用IDE的时候。
3.1jdb 命令
3.2 jdb 调试命令
3.2类调试
我们先以简单的一个java类开始调试。
- 先编写一个可编译的java 类
package cn.restar.open.origin.common;
public class JdbTest {
public static void main(String[] args) {
int num = 10;
int numTwo = 5;
int result = num / numTwo;
System.out.println(result);
}
}
2.使用javac -g 编译
javac -g JdbTest.java
使用后会生成一个class 文件
- 使用jdb 开始调试
jdb JdbTest.java
- 如果使用list 时 找不到源文件那么此时需要使用 use 此时调试java文件的第一层包名之上的一层目录,这样既可正常查看源码。例如:
F:\mystorage\tomcat_demo\src\main\java\cn\restar\open\origin\common
那么此调试示例java文件的第一层包名(cn.restar.open.origin.common
)之上的一层目录 是为F:\mystorage\tomcat_demo\src\main\java
5.如果 使用 locals 时本地变量不可用,那么使用javac 时需要使用 -g 使生成的class 文件包含调试信息。
3.3 jar包调试
- 给即将启动的jar 包增加如下参数
- -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:40004
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:40004 -jar xxx.jar
- 使用jdb 命令连上已经启动的jvm
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=5005 -sourcepath (源码路径,和类调试源文件一样)
- 此时已经连上了对应的jvm。并且可以查看源码。其余的操作类似
四.jcmd
新增了一个命令行工具jcmd。它是一个多功能工具,可以用来导出堆,查看Java进程,导出线程信息,执行GC等。
- 通过下述命令可以查看当前正在运行的jvm
jcmd -l
2. 在指定某个pid 之后可以查看对应的jvm 支持什么操作
4.1命令详解
4.1.1 Compiler.codecache
含义:打印代码缓存布局和边界
4.1.2 Compiler.codelist
含义:打印代码缓存中处于活动状态的所有已编译方法。
4.1.3 Compiler.queue
含义:打印排队等待编译的方法。
4.1.4 Compiler.directives_add filename arguments
含义:从文件添加编译器指令。
4.1.5 Compiler.directives_clear
含义:删除所有编译器指令
4.1.6 Compiler.directives_print
含义:打印所有活动的编译器指令。
4.1.7 Compiler.directives_remove
含义:删除最新添加的编译器指令。
4.1.8 GC.class_histogram [options]
含义:提供有关 Java 堆使用情况的统计信息。
jcmd pid GC.class_histogram [options]
options:
- -all
4.1.9 GC.class_stats [options] [arguments]
含义:提供有关 Java 类元数据的统计信息。
jcmd pid GC.class_stats [options] [arguments]
options:
- -all (可选)显示所有列(
- -csv (可选)以 CSV(逗号分隔值)格式打印电子表格
- -help (可选)显示所有列的含义
arguments:想显示的列内容,如果不填则默认为
InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total
//可查看能显示的列
jcmd pid GC.class_stats -help
以下命令显示出的 Java 类元数据的统计信息
jcmd pid GC.class_stats -csv
4.1.10 GC.finalizer_info
含义:提供有关 Java 终结队列的信息
4.1.11 GC.heap_dump [options] [arguments]
含义:生成 Java 堆的 HPROF 格式转储
options:
- -all
arguments:
- filename: 转储文件的名称(字符串,无默认值)
4.1.12 GC.heap_info
含义:提供通用的 Java 堆信息
4.1.13 GC.run , GC.run_finalization
-
GC.run
含义:等同于调用 java.lang.System.gc() -
GC.run_finalization
含义:等同于调用 java.lang.System.runFinalization()
4.1.14 Thread.print [options]
含义:打印带有堆栈跟踪的所有线程。
4.1.15 VM.system_properties ,VM.version ,VM.uptime ,VM.native_memory ,VM.flags [options] ,VM.log [options], VM.info
-
VM.system_properties
含义:打印系统属性。 -
VM.version
含义:打印 JVM 版本信息。 -
VM.uptime
含义:打印 JVM 版本信息。 -
VM.native_memory
含义:打印本机内存使用情况 -
VM.flags [options]
含义:打印 VM 标志选项及其当前值。 -
VM.log [options]
含义:列出当前日志配置,启用/禁用/配置日志输出,或轮换所有日志。 -
VM.info
含义:打印有关 JVM 环境和状态的信息。
如果要查看所有参数,可点击此链接 java11
五.javap
使用 javap 命令反汇编一个或多个类文件。
javap [options] classes
5.1常用命令:
//输出行号和本地变量表
javap -l Myclass.class
//对代码进行反汇编。
java -c Myclass.class
//输出附加信息 输出的内容比较多
javap -v Myclass.class
//输出内部类型签名
java -s Myclass.class
javap -l -c -s -v Myclass.class
六.keytool
keytool 是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务
6.1名词解释
6.1.1 KeyStore
密钥库是存储了密钥、X.509证书链及受信任证书的数据库。
6.1.2 KeyStore Entries
密钥库存在不同类型的条目,两种最适用于keytool的条目类型包括密钥条目与受信任证书条目。
每个密钥条目都包含敏感的密钥信息,它们以受保护的形式存储,以防未授权访问。通常,以这种形式存储的条目对应的密钥是秘密密钥,或者是伴随着对应公钥的证书链的私钥。
每个受信任证书条目都包含一个属于另一方的单独的公钥证书。它被称为”受信任证书”是因为密钥库的所有人信任这个证书中的公钥确实属于特定的身份,通过证书中的“主体”(所有人)可以进行身份验证。证书的颁发者对证书进行证实,通过对证书进行签名的方式。
6.1.3. KeyStore Aliases
所有的密钥库条目在访问时都需要通过独特的别名。 当使用以下命令向密钥库添加条目时,都需要指定别名:
使用-genseckey命令产生秘密密钥; 使用-genkeypair命令产生密钥对;
使用-importcert命令添加证书或证书链至受信任的证书列表中。 后续的keytool命令在操作对应的条目时,必须使用相同的别名。
6.1.4. Certificate Chains
keytool可以创建并管理密钥库密钥条目,每个密钥条目包含一个私钥与对应的证书”链”。证书链中的第一个证书包含私钥相应的公钥。
当密钥在最初被创建时(参考-genkeypair命令),链开始仅包含一个元素,即一个自签名证书。自签名证书的发行者(签名者)与证书主体(被证书认证的公钥对应的实体)相同。无论何时使用-genkeypair命令产生一个新的公/私钥对,都会将公钥包含进一个自签名证书中。
之后,当证书签名请求被创建(参考-certreq命令)并被发送至认证机构(CA)后,需要将CA的返回进行导入(参考-importcert命令),自签名证书将会被证书链代替。在证书链底部是由CA认证主体的公钥颁发的证书(回复),证书链中的下一个证书是用于认证CA的公钥。
在许多情况下,CA返回的证书是自签名证书(CA认证自己公钥的证书)且位于链中的最后一个。在其他情况下,CA返回的是证书链。在这种情况下,链底部的证书也是由CA签名验证密钥条目的公钥的证书。但链中的第二个证书由不同的CA进行签名,认证接收CSR的CA的公钥。然后,链中的下一个证书将是用于验证第二个CA的密钥的证书。如此直到达到自签名”根”证书。链中的每个证书(第一个之后的)都需要验证前一个证书的签名者的公钥。
6.1.5. The cacerts Certificates File
名为”cacerts”的证书文件保存在安全属性目录,java.home/lib/security,java.home是JAVA的运行时环境目录
“cacerts”文件代表系统范围的保存CA证书的密钥库。系统管理员可以通过keytool对该文件进行配置与管理,需要指定”JKS”密钥库类型。”cacerts”密钥库文件附带一些CA根证书。
“cacerts”密钥库文件的初始密码是”changeit”。
由于你信任cacerts文件中的CA,作为对其他实体进行证书签名与颁发的实体,你必须仔细管理cacerts文件。cacerts文件应该仅包含你信任的CA证书。验证cacerts文件中捆绑的受信任CA根证书并决定你自己的信任范围是使用者的责任。当需要从cacerts文件中去除一个不受信任的CA证书时,可使用keytool命令的删除选项。你可以在JRE的安装目录中找到cacerts文件。
注意:
jdk的bin目录、jdk的jre\bin目录、jre的bin目录中可能均存在keytool。
当使用jdk的bin目录或jdk的jre\bin目录中的keytool时,会使用jdk的jre\lib\security目录中的cacerts文件;
当使用jre的bin目录中的keytool时,会使用jre的lib\security目录中的cacerts文件。
6.1.6. X.500 Distinguished Names
X.500识别名用于识别实体,如X.509证书中的主体与发布者(签发人)域。keytool支持的内容如下。
commonName – 常用名,当证书被用于HTTPS时,该值应为对应的域名
organizationUnit – 小型组织(如部门或分部)名称
organizationName – 大型组织名称
localityName – 地区(城市)名称
stateName – 州或省名称
country – 两个字母的国家代码
当使用-genkeypair的-dname选项指定X.500识别名时,-dname选项的参数名与上述参数的对应关系如下:
CN – commonName
OU – organizationUnit
O – organizationName
L – localityName
S – stateName
C – country
示例命令如下:
keytool -genkeypair -dname "CN=xx, OU=xx, O=xx, L=xx, ST=xx, C=xx
-dname选项的参数名称不区分大小写,如”CN”,”cn”及”Cn”含义相同。各参数需要按照上述顺序依次出现,但可以省略部分参数。
当通过命令行指定-dname选项时,若某个参数值中出现了逗号,需要使用“\”转义;当通过标准输入指定-dname选项时,参数值中的逗号不需要进行转义。示例如下。
cn=peter schuster, o=Sun Microsystems\, Inc., o=sun, c=us
6.2生成密钥库
//生成非对称密钥库
keytool -genkeypair -alias xinqiudazhan.com -keyalg rsa -keysize 2048 -dname xingqiudazhan.com -validity 3650 -keypass 123456 -keystore=xinqiudazhan.jks -storepass 123456 -storetype JKS
重点参数
-
-keyalg
包含 EC 、RSA 、DSA 、 RSASSA-PSS 、 DH -
-keysize
EC默认256, RSA 默认2048 ,DSA 默认2048 , DH默认2048 , RSASSA-PSS默认2048。可以指定一个合适的keysize 比如可以为1056 等 -
-storetype
JDK11支持的密钥库类型包JKS、PKCS12、DKS、CaseExactJKS 、JCEKS 、PKCS11、Windows-MY 、Windows-ROOT。 默认为 PKCS12
6.3 生成证书请求
keytool -certreq [option]
//示例
keytool -certreq -alias xinqiudazhan.com -keystore ./xinqiudazhan.jks -file xinqiudazhan.csr
6.4 生成证书
keytool -gencert -infile ./xinqiudazhan.csr -outfile xinqiudazhan.cer -alias xinqiudazhan.com -keystore ./xinqiudazhan.jks
6.5 导入证书
//导入ca根证书
keytool -importcert -file ./rsa.oca.pem -keystore cacert -alias cacert.com
//导入中间证书
keytool -importcert -file ./rsa.oca.pem -keystore cacert -alias oacert.com
6.6查看证书
keytool -list -v -keystore ./cacert
显示的密钥库内容包含:Keystore类型、Keystore提供者、条目数量及每个条目的信息。
密钥库条目的类型包含trustedCertEntry、PrivateKeyEntry、SecretKeyEntry。
当条目类型为trustedCertEntry时,显示的内容包含:别名名称、创建日期、条目类型及证书信息。
当条目类型为PrivateKeyEntry时,显示的内容包含:别名名称、创建日期、条目类型及证书信息。
当条目类型为SecretKeyEntry时,显示的内容包含:别名名称、创建日期、条目类型。
通过-importcert命令生成的条目类型为trustedCertEntry。
通过-genkeypair命令生成的条目类型为PrivateKeyEntry。
通过-genseckey命令生成的条目类型为SecretKeyEntry。
当条目类型是trustedCertEntry,就相当于这个证书签发的证书都是可信的。
6.7 生成自签名证书和ssl 验证。
6.7 生成自签名证书和ssl 验证。
-
首先我们先创建一个服务端密钥库(server_key_store),使用上述说的命令创建即可。
-
使用这个密钥库(server_key_store)导出一张证书,将这张证书发给客户端。让客户端
将此证书导入信任库(client_trust_store)
-
然后我们创建一个客户端密钥库(client_key_store)
-
使用这个密钥库(client_key_store)导出一张证书,将这张证书发给服务端。让服务端
将此证书导入信任库(server_trust_store)
1.客户端要做的操作
1.创建Client端KeyStore文件clientKeys.jks,用于虚构的通信者 Client的证书 :
>>keytool -genkey -alias client -keysize 1024 -validity 3650 -keyalg RSA
-dname "CN=Aclie, OU=Developer,O=Iwgame, L=Shanghai, S=Shanghai, C=CH"
-keypass 123456 -storepass 123456 -keystore clientKeys.jks
==>这一步生成了clientKeys.jks
2.导出客户端 Alice公钥证书,并将client.cer文件发给netty服务使用者
>>keytool -export -alias alice -keystore clientKeys.jks -file client.cer -storepass 123456
==>这一步生成client.cer
3.创建客户端KeyStore文件clientTurst.jks并导入服务端公钥证书(从netty服务端机器那拿到server.cer文件 )
>>keytool -import -alias server -keystore clientTrust.jks -file server.cer -keypass 123456 -storepass 123456
==>这一步生成了clientTurst.jks
client共创建文件如下:
clientKeys.jks
clientTurst.jks
client.cer==>给server端用
参数说明:
-alias 产生别名
-validity:指定创建的证书有效期多少天
-keyalg :指定密钥的算法
-dname :指定证书拥有者信息 CN=commonName OU=organizationUnit O=organizationName
L=localityName S=stateName C=country
-keysize 指定密钥长度
-storepass 指定密钥库的密码
-keypass 指定别名条目的密码
-keystore 指定密钥库的名称(产生的各类信息将不在.keystore文件中)
-export 将别名指定的证书导出到文件 keytool -export -alias caroot -file caroot.crt
-file 参数指定导出到文件的文件名
2.服务端要做的操作
1.创建server端KeyStore文件serverKeys.jks,用于虚构的通信者 Client的证书 :
>>keytool -genkey -alias server -keysize 1024 -validity 3650 -keyalg RSA
-dname "CN=BOB, OU=Developer,O=Iwgame, L=Shanghai, S=Shanghai, C=CH"
-keypass 123456 -storepass 123456 -keystore serverKeys.jks
==>这一步生成了serverKeys.jks
2.生成服务端 BOB公钥证书,并将client.cer文件发给netty客户端使用者
>>keytool -export -alias server -keystore serverKeys.jks -file server.cer -storepass 123456
==>这一步生成server.cer
3.创建客户端KeyStore文件serverTurst.jks并导入服务端公钥证书(从nettyke客户端机器那拿到client.cer文件 )
>>keytool -import -alias client -keystore serverTrust.jks -file client.cer -keypass 123456 -storepass 123456
==>这一步生成了serverTurst.jks
server共创建文件如下:
serverKeys.jks
serverTurst.jks
server.cer==>给client端用
6.7.1生成证书提取公私钥
#生成密钥库 ,也就相当于生成了一张自签名的证书 和 私钥
keytool -genkeypair -alias abc -keyalg RSA -keypass abc -keystore abc.jks -storepass abc -validity 3650
# 生成pfx 形式密钥库
keytool -v -importkeystore -srckeystore abc.jks -srcstoretype jks -srcstorepass abc -destkeystore abc.pfx -deststoretype pkcs12 -deststorepass abc -destkeypass abc
#显示在屏幕上
openssl pkcs12 -in abc.pfx -nocerts -nodes
#输出到文件
openssl pkcs12 -in abc.pfx -nocerts -nodes -out abc.key
文章出处登录后可见!