1.Java常用命令

jps:查看本机的Java进程信息(显示系统中所有Hotspot虚拟机进程)

jstack:打印线程的栈信息,制作线程Dump(显示虚拟机的线程栈信息)

jmap:打印内存映射,只做堆Dump(用于生成虚拟机的内存快照信息)

jinfo:显示虚拟机的配置信息

jstat:性能监视工具(收集Hotspot虚拟机各方面运行数据)

jhat:内存分析工具

jconsole:简易的可视化控制台

jvisualvm:功能强大的控制台

打印某个类的常量池:javap -v Test.class

查看类的加载顺序:java -verbose:class Test

反编译字节码:javap -v -c Test

2.什么是Java Dump?有什么用?

Java Dump就是虚拟机的运行时快照,其将Java虚拟机运行时的状态和信息保存到文件中去。作用:可以了解程序运行时,虚拟机中的运行时状态信息;针对非业务逻辑性的BUG,如内存泄漏、内存溢出等。

3.制作Java Dump

使用Java虚拟机制作Dump:

-xx:+HeapDumpOnOutOfMemoryError 指示虚拟机在发生内存不足错误时,自动生成堆Dump。

使用图形工具制作Dump:

使用JDK (1.6) 自带的工具:Java VisualVM

使用命令行制作Dump

jstack:制作线程Dump

jmap:制作堆Dump

4.常用命令之jps

命令格式:

jps [options] [hostid]

显示当前所有Java进程pid的命令。

使用jps -help查看帮助:

$ jps -help

$jps -q

只显示pid,不显示class名称,jar文件名和传递给main 方法的参数

$jps -i

输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名

$jps -v

输出传递给JVM的参数

$jps -m

输出启动时传递给main函数的参数

执行示例:

$ jps -l

3733 sun.tools.jps.Jps

3700 com.leanworld.JVMTools

com.leanworld.JVMTools即为上面的示例代码执行类。

5.常用命令之javap

javap是jdk自带的一个工具,可以对代码反编译,也可以查看java编译器生成的字节码。

javap命令分解一个class文件,它根据options来决定到底输出什么。如果没有使用options,那么javap将会输出包,类里的protected和public域以及类里的所有方法。javap将会把它们输出在标准输出上。来看这个例子,先编译(javac)下面这个类。

可以尝试:命令行上键入javap DocFooter

加入了-c,即javap -c DocFoote

javap可以用于反编译和查看编译器编译后的字节码。用java -c比较多;该命令用于列出每个方法所执行的JVM指令,并显示每个方法的字节码的实际作用。

6.常用命令之jstack

命令格式:

jstack [ option ] pid

jstack是JDK自带的一种堆栈跟踪工具。

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程执行的方法堆栈的集合,生成线程快照的主要目的是定位线程长时间停顿的原因,如线程间死锁、死循环等。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么。如果java程序崩溃,生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松的知道java程序是如何崩溃和在程序何处发出问题。

尝试:jstack -help

-l 长列表,打印关于锁的附加信息;-F 当-l没有响应时强制打印栈信息;-m 打印java和native/c/c++框架的所有栈信息;pid用jps查询。

在死锁时可以查看观察

执行示例:

$ jstack 3700
2012-01-30 16:36:05
Full thread dump Java HotSpot(TM) Server VM (17.0-b16 mixed mode):
"Attach Listener" daemon prio=10 tid=0xaca16c00 nid=0x1384 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"Low Memory Detector" daemon prio=10 tid=0xaca00c00 nid=0x1366 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
"CompilerThread1" daemon prio=10 tid=0x08e58800 nid=0x1365 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"CompilerThread0" daemon prio=10 tid=0x08e56800 nid=0x1364 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" daemon prio=10 tid=0x08e54c00 nid=0x1363 runnable [0x00000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" daemon prio=10 tid=0x08e39000 nid=0x1361 in Object.wait() [0xac943000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
waiting on <0xb10e0230> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
locked <0xb10e0230> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=10 tid=0x08e34400 nid=0x1360 in Object.wait() [0xacb94000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
waiting on <0xb10e30d0> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:485)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
locked <0xb10e30d0> (a java.lang.ref.Reference$Lock)
"main" prio=10 tid=0x08d7bc00 nid=0x135a waiting on condition [0xb6a8a000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.leanworld.JVMTools.createList(JVMTools.java:23)
at com.leanworld.JVMTools.main(JVMTools.java:29)
"VM Thread" prio=10 tid=0x08e31c00 nid=0x135f runnable
"GC task thread#0 (ParallelGC)" prio=10 tid=0x08d83800 nid=0x135b runnable
"GC task thread#1 (ParallelGC)" prio=10 tid=0x08d85000 nid=0x135c runnable
"GC task thread#2 (ParallelGC)" prio=10 tid=0x08d86400 nid=0x135d runnable
"GC task thread#3 (ParallelGC)" prio=10 tid=0x08d87c00 nid=0x135e runnable
"VM Periodic Task Thread" prio=10 tid=0xaca02c00 nid=0x1367 waiting on condition
JNI global references: 854

通过输出信息可以看出当前main线程处于TIMED_WAITING状态,因为执行到示例代码中Thread.sleep(100);这行的缘故。

常用参数:

-l 除堆栈外,显示锁的附加信息

-F 当请求不被响应时,强制输出线程堆栈

-m 混合模式,打印java和本地C++调用的堆栈信息

7.常用命令之jmap

命令格式:

jmap [ option ] pid

jmap主要用于打印指定Java进程的共享内存映射或堆内存细节,可以用jmap生成堆Dump。

什么是堆Dump?

是反映内存使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。一般在GC异常、内存不足的情况下,我们怀疑又内存泄漏,这时候我们就可以制作Heap Dump来查看情况,分析原因。

尝试:输入jmap,会出现-help的信息

查看内存使用情况,用jmap -heap pid

产看堆内存(histogram)中的对象数量及大小,用jmap -histo pid(用histo:live时,会先触发gc,然后统计信息)

将内存使用情况输出到文件,执行的命令是:jmap -dump:fomat=b,file=heapDump pid,然后用jhat命令可以参看:jhat -port 5000 heapDump,然后在浏览器中访问:http:localhost:5000/产看信息

执行示例:

$ jmap -dump:format=b,file=dump.tmp 3700
Dumping heap to /home/learnworld/dump.tmp ...
Heap dump file created

上面这个命令生成了dump.tmp这个dump文件。生成的dump文件可以使用Eclipse Memory Analyzer/jhat等工具进行分析。

$ jmap -permstat 3700
Attaching to process ID 3700, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17.0-b16
1355 intern Strings occupying 183024 bytes.
finding class loader instances ..Finding object size using Printezis bits and skipping over...
done.
computing per loader stat ..done.
please wait.. computing liveness....done.
class_loader classes bytes parent_loader alive? type
 320 1437208 null live 
0xb1170250 10 77120 0xb11706b8 live sun/misc/Launcher$AppClassLoader@0xad34eb70
0xb11706b8 0 0 null live sun/misc/Launcher$ExtClassLoader@0xad303d40
total = 3 330 1514328 N/A alive=3, dead=0 N/A

常用参数:

-dump 生成堆dump文件,格式为: -dump:[live,]format=b,file=

-heap 显示java堆的详细信息,包括垃圾回收期、堆配置和分代信息等

-histo 显示堆中对象的统计信息,包括类名称,对应的实例数量和总容量

-permstat 统计持久代中各ClassLoader的统计信息。

8.jstat

命令格式:

jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]

vmid表示虚拟机唯一标识符,如果是本地虚拟机进程,与LVMID一致,通常为本地虚拟机进程号。 interval表示查询间隔时间,count表示查询次数。如果省略interval和count参数,表示查询一次。

执行示例:

$ jstat -gcutil 3700 500 4

S0 S1 E O P YGC YGCT FGC FGCT GCT

50.00 0.00 60.78 0.50 12.76 214 0.049 0 0.000 0.049

0.00 25.00 20.27 0.50 12.76 215 0.049 0 0.000 0.049

0.00 25.00 70.91 0.50 12.76 215 0.049 0 0.000 0.049

50.00 0.00 20.27 0.50 12.76 216 0.049 0 0.000 0.049

S0和S1表示Survivor0和Survivor1,E表示新生代Eden,O表示老年代Old,P表示持久代Permanent,以上各参数值表示已使用空间占比。 YGC表示young gc次数,YGCT表示young gc总耗时。FGC表示Full gc次数,FGCT表示full gc总耗时。GCT表示所有gc总耗时时间。

常用参数:

class 类装载相关信息.

compiler JIT编译器编译过的方法、耗时等.

gc java堆信息和垃圾回收状况.

gccapacity 关注java堆各个区的最大和最小空间.

gccause 类似gcutil,额外输出导致上一次gc的原因.

gcnew 新生代gc状况.

gcnewcapacity 关注新生代gc使用的最大和最小空间.

gcold 老年代gc状况.

gcoldcapacity 关注老年代gc使用的最大和最小空间.

gcpermcapacity 关注持久代gc使用的最大和最小空间.

gcutil 关注已使用空间占总空间比例.

printcompilation 输出已经被JIT编译的方法.

9.jinfo

命令格式:

jinfo [ option ] pid

执行示例:

$jinfo 3700
Attaching to process ID 5081, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17.0-b16
Java System Properties:
java.runtime.name = Java(TM) SE Runtime Environment
sun.boot.library.path = /home/learnworld/software/jdk1.6.0_21/jre/lib/i386
java.vm.version = 17.0-b16
java.vm.vendor = Sun Microsystems Inc.
java.vendor.url = http://java.sun.com/
path.separator = :
java.vm.name = Java HotSpot(TM) Server VM
file.encoding.pkg = sun.io
sun.java.launcher = SUN_STANDARD
user.country = CN
sun.os.patch.level = unknown
java.vm.specification.name = Java Virtual Machine Specification
user.dir = /home/learnworld/workspace/concurrency
java.runtime.version = 1.6.0_21-b06
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
java.endorsed.dirs = /home/learnworld/software/jdk1.6.0_21/jre/lib/endorsed
os.arch = i386
java.io.tmpdir = /tmp
line.separator =
...

VM Flags:

-Xmn10m -Xms40m -Xmx40m -Dfile.encoding=GBK -Xbootclasspath:/home/learnworld/software/jdk1.6.0_21/lib/tools.jar:/home/learnworld/software/jdk1.6.0_21/lib/sa-jdi.jar:/home/learnworld/software/jdk1.6.0_21/lib/jconsole.jar:/home/learnworld/software/jdk1.6.0_21/lib/htmlconverter.jar:/home/learnworld/software/jdk1.6.0_21/lib/dt.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/rt.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/resources.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/plugin.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/management-agent.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/jsse.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/jce.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/javaws.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/deploy.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/charsets.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/alt-rt.jar

可以看出,该命令可以方便我们查找需要的虚拟机信息,包含System.getProperties()信息。

常用参数:

-flag name 打印虚拟机该参数对应的值.

-flag [+-]name 使该参数生效或失效.

-flag name=value 修改相应参数的值.

-flags 打印传给jvm的参数值.

-sysprops 打印System.getProperties()信息.

注:

1、如果程序内存不足或频繁GC时,很可能存在内存泄漏的情况,此时就可以借助Java堆Dump查看对象的情况。

2、制作heap Dump 可以用jamp命令

3、可以先用jmap -heap查看内存的使用情况

4、使用jamp -histo:[live] 查看堆内存的使用情况,如果大量对象在持续被引用,并没有释放掉,则产生了内存泄漏,就要结合代码,把不用的对象释放掉。

5、也可以用jmap -dump:format=b,file= pid 将堆信息保存到文件中,然后用jhat产看。

6、如果出现内存泄漏等情况,建议多Dump几次。

实战代码:

package com.leanworld;
import java.util.ArrayList;
import java.util.List;
/**
虚拟机常用工具使用示例代码 启动参数: -Xmn10m -Xms40m -Xmx40m
@author learnworld 2012-1-30 下午01:37:14
*/
public class JVMTools {
public static void createList(int count) throws InterruptedException {
for (int j = 0; j < count; j++) {
List<_1mobject> list = new ArrayList<_1mobject>();
Thread.sleep(100);
list.add(new _1MObject());
}
}
public static void main(String[] args) throws InterruptedException {
createList(5000);
}
}
/**
一个大约1M的对象
*/
class _1MObject {
public byte[] _1M = new byte[1024 * 1024];
}