一、jmap基本用法
jmap(java memory map)是jdk自带的内存详细信息监控工具,jdk6之后在linux,unix或windows上都能使用,但在windows上功能有所限制。jmap在命令行上使用打印出运行的jvm或core文件的内存统计信息。如果不带任何参数单独使用jmap命令,那将打印出共享对象的列表。如果想看到更多指定的信息,可以使用
-heap,-histo或-permstat选项。
除此之外,jdk6开始还提供了
-dump:format=b,file=fileName的选项,可以dump出内存的使用情况到一个指定文件名的二进制文件中。这个文件可以配合jdk自带的jhat工具或其他第三方工具来分析(
jhat对于大的二进制文件分析耗时且响应慢,还有可能内存溢出,个人一般使用第三方mat插件来分析)。
如果jmap pid命令因为pid挂死而无响应,可以使用-F选项强制输出(
这个选项只能在Solaris和linux上使用)。
jmap是在Solaris os和linux版本中提供的功能,但jdk6之后的windows版本也提供了,不过只有jmap –dump:format=b,file=fileName和jmap –histo[:live] pid两个选项可以使用。
1.0 jmap命令格式
语法:
jmap [ option ] pid
jmap [ option ] executable core
jmap [ option ] [server-id@]remote-hostname-or-IP
参数说明:
1)options:
executable:Java executable from which the core dump was produced.
core: 将被打印信息的core dump文件
remote-hostname-or-IP:远程debug服务的主机名或ip
server-id:唯一id,假如一台主机上多个远程debug服务
2)基本参数:
-dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件.
-finalizerinfo 打印正等候回收的对象的信息.
-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.
-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
-permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.
-F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效.
-h | -help 打印辅助信息
-J 传递参数给jmap启动的jvm.
pid 需要被打印配相信息的java进程id,创业与打工的区别 - 博文预览,可以用jps查问.
1.1 堆内存配置和使用 -heap
-heap选项可以获取以下heap信息:
1)gc信息,包括gc算法,并行gc使用的线程数等。
2)堆配置。包括jvm中设置的和启动时指定的内存属性配置,如最大最小设置等。
3)堆使用概要。如每一代内存的使用情况。
示例:
$ jmap -heap 29620
输出:
Attaching to process ID 29620, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 1.6.0-rc-b100
using thread-local object allocation.
Mark Sweep Compact GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 67108864 (64.0MB)
NewSize = 2228224 (2.125MB)
MaxNewSize = 4294901760 (4095.9375MB)
OldSize = 4194304 (4.0MB)
NewRatio = 8
SurvivorRatio = 8
PermSize = 12582912 (12.0MB)
MaxPermSize = 67108864 (64.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 2031616 (1.9375MB)
used = 70984 (0.06769561767578125MB)
free = 1960632 (1.8698043823242188MB)
3.4939673639112905% used
Eden Space:
capacity = 1835008 (1.75MB)
used = 36152 (0.03447723388671875MB)
free = 1798856 (1.7155227661132812MB)
1.9701276506696428% used
From Space:
capacity = 196608 (0.1875MB)
used = 34832 (0.0332183837890625MB)
free = 161776 (0.1542816162109375MB)
17.716471354166668% used
To Space:
capacity = 196608 (0.1875MB)
used = 0 (0.0MB)
free = 196608 (0.1875MB)
0.0% used
tenured generation:
capacity = 15966208 (15.2265625MB)
used = 9577760 (9.134063720703125MB)
free = 6388448 (6.092498779296875MB)
59.98769400974859% used
Perm Generation:
capacity = 12582912 (12.0MB)
used = 1469408 (1.401336669921875MB)
free = 11113504 (10.598663330078125MB)
11.677805582682291% used
包含堆属性的配置和各个代(HotSpot VM的内存是分代管理)内存的使用统计。
1.2 运行进程的堆直方图统计 -histo
-histo选项可以用来获取
基于类名的堆内存统计。可以输出对象实例数量,内存统计和实例对应的类名。如果想获取一个实例的大小,可以使用内存数除以对应的实例个数。
示例:
$ jmap -histo 29620
输出:
num #instances #bytes class name
--------------------------------------
1: 1414 6013016 [I
2: 793 482888 [B
3: 2502 334928 <constMethodKlass>
4: 280 274976 <instanceKlassKlass>
5: 324 227152 [D
6: 2502 200896 <methodKlass>
7: 2094 187496 [C
8: 280 172248 <constantPoolKlass>
9: 3767 139000 [Ljava.lang.Object;
10: 260 122416 <constantPoolCacheKlass>
11: 3304 112864 <symbolKlass>
12: 160 72960 java2d.Tools$3
13: 192 61440 <objArrayKlassKlass>
14: 219 55640 [F
15: 2114 50736 java.lang.String
16: 2079 49896 java.util.HashMap$Entry
17: 528 48344 [S
18: 1940 46560 java.util.Hashtable$Entry
19: 481 46176 java.lang.Class
20: 92 43424 javax.swing.plaf.metal.MetalScrollButton
... more lines removed here to reduce output...
1118: 1 8 java.util.Hashtable$EmptyIterator
1119: 1 8 sun.java2d.pipe.SolidTextRenderer
Total 61297 10152040
排序是按照每类实例使用总内存的降序。其中class name对应的就是Class文件里的class的标识:
B代表byte
C代表char
D代表double
F代表float
I代表int
J代表long
Z代表boolean
S代表short
void用V表示
内部名就是带全包路径的表示法,例如String的内部名是java/lang/String
前边有[代表数组,[I 就相当于int[]
对象用[L+类名表示
1.3 core文件的堆直方图统计
在core文件上使用jmap –histo命令时可以输出每个类的实例个数,大小和名称。HotSpot vm的
自身的类名称前面会带前缀*.
示例:
& jmap -histo /net/koori.sfbay/onestop/jdk/6.0/promoted/all/b100/binaries/ solaris-sparcv9/bin/java core
输出:
Attaching to core core from executable /net/koori.sfbay/onestop/jdk/6.0/
promoted/all/b100/binaries/solaris-sparcv9/bin/java, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.6.0-rc-b100
Iterating over heap. This may take a while...
Heap traversal took 8.902 seconds.
Object Histogram:
Size Count Class description
-------------------------------------------------------
4151816 2941 int[]
2997816 26403 * ConstMethodKlass
2118728 26403 * MethodKlass
1613184 39750 * SymbolKlass
1268896 2011 * ConstantPoolKlass
1097040 2011 * InstanceKlassKlass
882048 1906 * ConstantPoolCacheKlass
758424 7572 char[]
733776 2518 byte[]
252240 3260 short[]
214944 2239 java.lang.Class
177448 3341 * System ObjArray
176832 7368 java.lang.String
137792 3756 java.lang.Object[]
121744 74 long[]
72960 160 java2d.Tools$3
63680 199 * ObjArrayKlassKlass
53264 158 float[]
... more lines removed here to reduce output...
1.4 获取持久代(方法区)信息 -permstat
持久代存储的是类信息,方法信息,字符串池等。配置持久代内存大小对应用程序动态产生和加载大量类很重要。如果加载的类太多或太多的internalized字符串就可能抛出OutOfMemoryError。
可以使用-permstat选项输出持久代内存的统计信息。示例:
$ jmap -permstat 29620
输出:
Attaching to process ID 29620, please wait...
Debugger attached successfully.
Client compiler detected.
JVM version is 1.6.0-rc-b100
12674 intern Strings occupying 1082616 bytes.
finding class loader instances ..Unknown oop at 0xd0400900
Oop's klass is 0xd0bf8408
Unknown oop at 0xd0401100
Oop's klass is null
done.
computing per loader stat ..done.
please wait.. computing liveness.........................................done.
class_loader classes bytes parent_loader alive? type
<bootstrap> 1846 5321080 null live <internal>
0xd0bf3828 0 0 null live sun/misc/Launcher$ExtClassLoader@0xd8c98c78
0xd0d2f370 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0c99280 1 1440 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0b71d90 0 0 0xd0b5b9c0 live java/util/ResourceBundle$RBClassLoader@0xd8d042e8
0xd0d2f4c0 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0b5bf98 1 920 0xd0b5bf38 dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0c99248 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0d2f488 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0b5bf38 6 11832 0xd0b5b9c0 dead sun/reflect/misc/MethodUtil@0xd8e8e560
0xd0d2f338 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0d2f418 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0d2f3a8 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0b5b9c0 317 1397448 0xd0bf3828 live sun/misc/Launcher$AppClassLoader@0xd8cb83d8
0xd0d2f300 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0d2f3e0 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0ec3968 1 1440 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0e0a248 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0c99210 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0d2f450 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0d2f4f8 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
0xd0e0a280 1 904 null dead sun/reflect/DelegatingClassLoader@0xd8c22f50
total = 22 2186 6746816 N/A alive=4, dead=18 N/A
二、windows下定时执行jmap获取信息
linux下定时任务可以使用cron来实现,windows下倒是费了下工夫,没有在控制面板配置定时任务,觉得使用命令行更好控制些。比如在windows下想定时执行jmap –histo和jmap –dump命令,则可以如下操作:
step1:jmap_histo.bat
set filename=jmap_%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%.txt
echo %filename%
jmap -histo:live 78104 > %filename%
exit
step2:jmap_dump.bat
set filename=jmap_dump_%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%.hprof
echo %filename%
jmap -dump:live,format=b,file=%filename% 78104
step3:task.bat
@echo off
rem 指定要执行的bat文件的路径和名称。
:loop
start /min jmap_histo.bat
rem 900是定时任务执行的间隔时间(单位:秒),这里是15分钟。其他不需要修改。
ping -n 900 127.1> nul
goto loop
参考资料:
http://www.oracle.com/technetwork/java/javase/tooldescr-136044.html
http://docs.oracle.com/javase/6/docs/technotes/tools/share/jmap.html
http://hbluojiahui.blog.163.com/blog/static/31064767201282091643613/
http://developer.51cto.com/art/201203/321422.htm
分享到:
相关推荐
- **线程池使用不当**:检查线程池是否因为未捕获异常或定时任务未执行导致资源无法释放。 - **容器类本地缓存**:大量使用HashMap、ArrayList等容器类保存数据时,未及时移除不再使用的数据。 - **静态集合类...
- `newScheduledThreadPool`:定时任务。 - **锁机制:** - **线程安全问题**:多个线程共享资源时,避免竞争条件。 - **重入锁**:允许已经获得锁的线程再次获取该锁。 - **产生死锁的四个条件**:互斥、请求...
以上就是从给定文件信息中提炼出的主要知识点,涵盖了JVM参数配置以及一些常用的系统和JVM监控工具的使用方法。这对于IT行业的开发者来说是非常实用的知识点,尤其是在进行性能调优和故障排查时尤为关键。
- **1.8 JVM监控**: 对于Java应用,使用JVM监控工具如`jps`、`jstat`、`jmap`等来检查虚拟机的运行状态,包括内存使用、线程状态等。 #### 五、构建性能监控平台 - **2.1 为什么构建基于云的端到端性能监控平台**:...
支持远程执行JDK自带工具命令,包含但不限于jps、jstat、jstack、jinfo、jmap、jcmd等 提供客户端交互工具,支持跨进程attach和远程连接功能 支持三种服务模式(可同时开启多个服务): jvmm服务:独有RPC协议,需...
1. **JUnit 用法**:JUnit是Java单元测试框架,before、beforeClass、after、afterClass是其生命周期方法。执行顺序是:beforeClass(类前置,只执行一次)、before(每个测试方法前执行)、测试方法、after(每个...
如果你使用Spring框架,可以利用`@Scheduled`注解和`TaskScheduler`接口来实现定时任务。这允许开发者在后台执行周期性任务,无需手动管理线程。 7. **Docker容器中的任务管理**: 当Java应用部署在Docker容器中...
1. JUnit用法:JUnit是一个Java语言的单元测试框架,通常需要了解如何编写测试类、测试方法,以及如何使用@Test、@Before、@After、@BeforeClass、@AfterClass等注解来组织测试代码。 2. 分布式锁:分布式锁用于在...
这通常需要在订单系统中设置定时任务,按照预定时间检查订单状态并执行相应的业务逻辑。 12. 后台服务变慢的可能原因:后台服务变慢可能原因包括数据库I/O瓶颈、内存泄漏、代码效率低下、资源竞争、外部依赖服务不...
作者使用jmap命令dump了heap,并使用MAT分析内存泄露,发现了jdbc中的一个类可能是内存泄露的原因。但实际上,整体占用堆容量并不多。作者也分析了线程数量,发现了大量的是在sleep的定时线程。 知识点四:Thread ...