JVM监控工具
Java的安装包自带了很多优秀的工具,善用这些工具对于监控和调试Java程序非常有帮助。常用工具如下:
jps
用途:jps用来查看JVM里面所有进程的具体状态, 包括进程ID,进程启动的路径等等。
常用参数:
-l: 输出完成的包名称;
-m: 输出程序的命令行输入参数;
-v: 输出完整的JVM参数。
jstack
用途:1)查看java程序崩溃生成core文件,获得core文件的java stack和native stack的信息;2)查看正在运行的java程序的java stack和native stack的信息:a) 查看运行的java程序呈现hung的状态;b) 跟踪Java的调用栈,剖析程序。
jinfo
用途:jinfo可观察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数;也可从core文件里面知道崩溃的Java应用程序的配置信息。
jstat
用途:jstat利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等。
语法结构:
Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
参数解释:
Options — 选项,我们一般使用 -gcutil 查看gc情况
vmid — VM的进程号,即当前运行的java进程号
interval– 间隔时间,单位为秒或者毫秒
count — 打印次数,如果缺省则打印无数次
具体option参数如下:
-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity:统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
-gcutil:统计gc时,heap情况
输出内容含义如下:
S0 — Heap上的 Survivor space 0 区已使用空间的百分比
S1 — Heap上的 Survivor space 1 区已使用空间的百分比
E — Heap上的 Eden space 区已使用空间的百分比
O — Heap上的 Old space 区已使用空间的百分比
P — Perm space 区已使用空间的百分比
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
示例
实例使用1:
[root@localhost bin]# jstat -gcutil 25444
S0 S1 E O P YGC YGCT FGC FGCT GCT
11.63 0.00 56.46 66.92 98.49 162 0.248 6 0.331 0.579
实例使用2:
[root@localhost bin]# jstat -gcutil 25444 1000 5
S0 S1 E O P YGC YGCT FGC FGCT GCT
73.54 0.00 99.04 67.52 98.49 166 0.252 6 0.331 0.583
73.54 0.00 99.04 67.52 98.49 166 0.252 6 0.331 0.583
73.54 0.00 99.04 67.52 98.49 166 0.252 6 0.331 0.583
73.54 0.00 99.04 67.52 98.49 166 0.252 6 0.331 0.583
73.54 0.00 99.04 67.52 98.49 166 0.252 6 0.331 0.583
我们可以看到,5次young gc之后,垃圾内存被从Eden space区(E)放入了Old space区(O),并引起了百分比的变化,导致Survivor space使用的百分比从73.54%(S0)降到0%(S1)。有效释放了内存空间。绿框中,我们可以看到,一次full gc之后,Old space区(O)的内存被回收,从99.05%降到67.52%。
图中同时打印了young gc和full gc的总次数、总耗时。而,每次young gc消耗的时间,可以用相间隔的两行YGCT相减得到。每次full gc消耗的时间,可以用相隔的两行FGCT相减得到。例如红框中表示的第一行、第二行之间发生了1次young gc,消耗的时间为0.252-0.252=0.0秒。
常驻内存区(P)的使用率,始终停留在98.49%左右,说明常驻内存没有突变,比较正常。
如果young gc和full gc能够正常发生,而且都能有效回收内存,常驻内存区变化不明显,则说明java内存释放情况正常,垃圾回收及时,java内存泄露的几率就会大大降低。但也不能说明一定没有内存泄露。
GCT 是YGCT 和FGCT的时间总和。
以上,介绍了Jstat按百分比查看gc情况的功能。其实,它还有功能,例如加载类信息统计功能、内存池信息统计功能等,那些是以绝对值的形式打印出来的,比较少用,在此就不做介绍。
[root@localhost bin]# ps -ef | grep java
root 25917 1 2 23:23 pts/2 00:00:05 /usr/local/jdk1.5/bin/java -Djava.endorsed.dirs=/usr/local/jakarta-tomcat-5.0.30/common/endorsed -classpath /usr/local/jdk1.5/lib/tools.jar:/usr/local/jakarta-tomcat-5.0.30/bin/bootstrap.jar:/usr/local/jakarta-tomcat-5.0.30/bin/commons-logging-api.jar -Dcatalina.base=/usr/local/jakarta-tomcat-5.0.30 -Dcatalina.home=/usr/local/jakarta-tomcat-5.0.30 -Djava.io.tmpdir=/usr/local/jakarta-tomcat-5.0.30/temp org.apache.catalina.startup.Bootstrap start
jstat -class pid:显示加载class的数量,及所占空间等信息。
实例使用3:
[root@localhost bin]# jstat -class 25917
Loaded Bytes Unloaded Bytes Time
2629 2916.8 29 24.6 0.90
jstat -compiler pid:显示VM实时编译的数量等信息。
实例使用4:
[root@localhost bin]# jstat -compiler 25917
Compiled Failed Invalid Time FailedType FailedMethod
768 0 0 0.70 0
jstat –gccapacity :可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小,如:PGCMN显示的是最小perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可以根据这个类推, OC是old内纯的占用量。
[root@localhost bin]# jstat -gccapacity 25917
NGCMN 640.0
NGCMX 4992.0
NGC 832.0
S0C 64.0
S1C 64.0
EC 704.0
OGCMN 1408.0
OGCMX 60544.0
OGC 9504.0
OC 9504.0 OC是old内纯的占用量
PGCMN 8192.0 PGCMN显示的是最小perm的内存使用量
PGCMX 65536.0 PGCMX显示的是perm的内存最大使用量
PGC 12800.0 PGC是当前新生成的perm内存占用量
PC 12800.0 PC是但前perm内存占用量
YGC 164
FGC 6
jstat -gcnew pid: new对象的信息
[root@localhost bin]# jstat -gcnew 25917
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
64.0 64.0 47.4 0.0 2 15 32.0 704.0 145.7 168 0.254
jstat -gcnewcapacity pid: new对象的信息及其占用量
[root@localhost bin]# jstat -gcnewcapacity 25917
NGCMN NGCMX NGC S0CMX S0C S1CMX S1C ECMX EC YGC FGC
640.0 4992.0 832.0 64.0 448.0 448.0 64.0 4096.0 704.0 168 6
jstat -gcold pid: old对象的信息。
[root@localhost bin]# jstat -gcold 25917
PC PU OC OU YGC FGC FGCT GCT
12800.0 12617.6 9504.0 6561.3 169 6 0.335 0.591
jstat -gcoldcapacity pid:old对象的信息及其占用量。
[root@localhost bin]# jstat -gcoldcapacity 25917
OGCMN OGCMX OGC OC YGC FGC FGCT GCT
1408.0 60544.0 9504.0 9504.0 169 6 0.335 0.591
jstat -gcpermcapacity pid: perm对象的信息及其占用量。
[root@localhost bin]# jstat -gcpermcapacity 25917
PGCMN PGCMX PGC PC YGC FGC FGCT GCT
8192.0 65536.0 12800.0 12800.0 169 6 0.335 0.591
jstat -printcompilation pid:当前VM执行的信息。
[root@localhost bin]# jstat -printcompilation -h3 25917 1000 5
每1000毫秒打印一次,一共打印5次,还可以加上-h3每三行显示一下标题。
Compiled Size Type Method
788 73 1 java/io/File <init>
788 73 1 java/io/File <init>
788 73 1 java/io/File <init>
Compiled Size Type Method
788 73 1 java/io/File <init>
788 73 1 java/io/File <init>
jmap
用途:观察运行中的jvm物理内存的占用情况,包括Heap size, Perm size等等。
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况
命令使用:
jmap -heap 2083 ---- 观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
jmap -histo 2083 | jmap -histo:live 2083 ---- 观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。
jmap -dump:live,format=b,file=heap.bin 2083 ---- dump java heap in hprof binary format。输出文件可用于进一步分析。
Java调优
使用Memory Analyzer tool(MAT)分析内存泄漏
Java调试辅助函数
调试Java程序经常需要知道Java进程PID、当前目录、Java Home、内存使用情况、执行特定命令等等。JavaDebug收集了上述这些常用的辅助调试函数。
import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.io.File; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Iterator; import java.util.Map; import java.util.Properties; public class JavaDebug{ public static int getPid() { RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); String name = runtime.getName(); // format: "pid@hostname" try { return Integer.parseInt(name.substring(0, name.indexOf('@'))); } catch (Exception e) { System.err.println(e.getMessage()); return -1; } } public static void printEnv(){ Map<String,String> map = System.getenv(); Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator(); Map.Entry<String, String> entry; while (iter.hasNext()) { entry = iter.next(); String name = entry.getKey(); String value = entry.getValue(); System.out.println(name + ": "+ value); } } public static void printProperties(){ Properties pros = System.getProperties(); pros.list(System.out); } public static String getPWD(){ return System.getProperty("user.dir"); } public static void printSimpleMemoryInfo(){ Runtime runTime = Runtime.getRuntime(); System.out.println("Total Mem:" + runTime.totalMemory() + " Max Mem:" +runTime.maxMemory() + " Free mem:" + runTime.freeMemory() ); } public static void printMemoryInfo(String info){ if( info != null){ System.out.println(info+ " JavaDebug:printMemoryInfo"); } printSimpleMemoryInfo(); ExecCommand("jmap " + getPid()); } public static void ExecCommand(String cmd){ System.out.println("Exec command: "+cmd); try{ Process pro = null; Runtime runTime = Runtime.getRuntime(); if (runTime == null) { System.err.println("Create runtime false!"); throw new RuntimeException("Create runtime false!"); } pro = runTime.exec(cmd); BufferedReader input = new BufferedReader(new InputStreamReader(pro.getInputStream())); PrintWriter output = new PrintWriter(new OutputStreamWriter(pro.getOutputStream())); String line; while ((line = input.readLine()) != null) { System.out.println(line); } input.close(); output.close(); pro.destroy(); } catch(IOException e) { System.err.println(e.getMessage()); e.printStackTrace(); throw new RuntimeException("run command error!"); } System.out.println("Exec command: "+cmd + " finish."); } public static void main(String[] args) throws Exception { printProperties(); //printEnv(); System.out.println("========================"); int pid = getPid(); System.out.println("pid: " + pid); System.out.println("pwd: " + getPWD()); printMemoryInfo(null); ExecCommand("ls -l"); ExecCommand("jmap " + pid); printMemoryInfo(null); } }
相关推荐
Java性能监控工具JProfiler是Java开发中的重要辅助软件,它为开发者提供了深入的性能分析功能,帮助优化应用程序的运行效率。JProfiler 4.3.2版本是该工具的一个历史版本,虽然较新版本可能拥有更多特性,但4.3.2...
**JVM TI (Java Virtual Machine Tool Interface)** 是Java虚拟机工具接口,它是Java平台标准版(Java SE)的一部分,提供了一种方式来实现对Java虚拟机的低级别监控和调试。JVM TI允许开发人员创建工具,如内存分析...
- **监控与调试工具**: 使用`jconsole`、`VisualVM`等工具可以帮助开发者诊断并发问题,识别性能瓶颈。 ### 实践案例 为了更好地理解Java并发编程的原理和技术细节,下面列举几个具体的实践案例: - **生产者消费...
- 使用重构工具(如 IntelliJ IDEA 的 Refactor 功能)辅助完成。 #### 23. 多线程编程 - 在多线程环境中正确使用同步机制。 - 避免死锁和竞态条件。 #### 24. 用户界面设计 - 如果使用 AWT 或 Swing 创建用户界面...
2. 性能调优:分析trace-file中的热点函数或系统调用,优化相应代码或配置。 3. 软件测试:在开发阶段,利用trace-file进行黑盒或白盒测试,验证软件功能的正确性。 4. 系统监控:通过持续收集和分析trace-file,...
5. **编译和调试工具**:在开发C语言嵌入式程序时,需要熟悉交叉编译工具链,如GCC(GNU Compiler Collection)和GDB(GNU Debugger)。它们允许在宿主机上编译目标平台的代码,并进行远程调试。 6. **驱动程序开发...
辅助类GenericOptionsParser,Tool和ToolRunner 编写单元测试 mapper reducer 本地运行测试数据 在本地作业运行器上运行作业 测试驱动程序 在集群上运行 打包 启动作业 MapReduce的Web界面 获取结果 作业调试 使用...
辅助类GenericOptionsParser,Tool和ToolRunner 编写单元测试 mapper reducer 本地运行测试数据 在本地作业运行器上运行作业 测试驱动程序 在集群上运行 打包 启动作业 MapReduce的Web界面 ...
11. **ABAP开发工具**:如SE80(SAP Development Workbench)、SE24(ABAP Editor)、SE38(ABAP Program Editor)等,是开发过程中不可或缺的辅助工具。 12. **ABAP与SAP NetWeaver**:理解ABAP在SAP NetWeaver...
- **包状态和JAVA会话状态**:检查程序中包的状态以及JAVA会话信息,确保资源正确释放。 - **查看结果集**:展示程序执行后的数据输出,用于分析和验证。 - **查看DBMS_OUTPUT**:利用Oracle内置的DBMS_OUTPUT包显示...
- **SQL跟踪**:记录SQL语句的执行情况,辅助性能调优。 #### 七、专用SQL - **使用SQL窗口**:专门用于编写和执行SQL查询。 - **结果表格处理**:操作查询结果集,支持数据导出和导入。 - **实例模式查询**:执行...