深入java内存查看与分析详解
2023-06-13 09:14:54 时间
-verbose:gc和-XX:+PrintTenuringDistribution等。
jconsole位于jdk目录下的bin目录,在windows下是jconsole.exe,在unix和linux下是jconsole.sh,jconsole可以监控本地应用,也可以监控远程应用。要监控本地应用,执行jconsolepid,pid就是运行的java进程id,如果不带上pid参数,则执行jconsole命令后,会看到一个对话框弹出,上面列出了本地的java进程,可以选择一个进行监控。如果要远程监控,则要在远程服务器的jvm参数里加入一些东西,因为jconsole的远程监控基于jmx的,关于jconsole详细用法,请见专门介绍jconsle的文章,我也会在博客里专门详细介绍jconsole。
和jconsole一样,运行jviusalvm,在jdk的bin目录下执行jviusalvm,windows下是jviusalvm.exe,linux和unix下是jviusalvm.sh。
Usage:
jmap-histo<pid>
(toconnecttorunningprocessandprinthistogramofjavaobjectheap
jmap-dump:<dump-options><pid>
(toconnecttorunningprocessanddumpjavaheap)
dump-options:
format=bbinarydefault
file=<file> dumpheapto<file>
Example: jmap-dump:format=b,file=heap.bin<pid>
jmap-histo<pid>在屏幕上显示出指定pid的jvm内存状况。以我本机为例,执行该命令,屏幕显示:
num#instances#bytes classname
----------------------------------------------
1:242062791864 <constMethodKlass>
2:223712145216 [C
3:242061940648 <methodKlass>
4: 19511364496 <constantPoolKlass>
5:265431282560 <symbolKlass>
6: 63771081744 [B
7: 1793909688 <constantPoolCacheKlass>
8: 1471614624 <instanceKlassKlass>
9:14581548336 [Ljava.lang.Object;
10: 3863513640 [I
11:20677496248 java.lang.String
12: 3621312776 [Ljava.util.HashMap$Entry;
13: 3335266800 java.lang.reflect.Method
14: 8256264192 java.io.ObjectStreamClass$WeakClassKey
15: 7066226112 java.util.TreeMap$Entry
16: 2355173304 [S
17: 1687161952 java.lang.Class
18: 2769150112 [[I
19: 3563142520 java.util.HashMap
20: 5562133488 java.util.HashMap$Entry
Total239019 17140408
为了方便查看,我删掉了一些行。从上面的信息很容易看出,#instance指的是对象数量,#bytes指的是这些对象占用的内存大小,classname指的是对象类型。
再看jmap的dump选项,这个选项是将jvm的堆中内存信息输出到一个文件中,在我本机执行
注意340是我本机的java进程pid,dump出来的文件比较大有10几M,而且我只是开了tomcat,跑了一个很简单的应用,且没有任何访问,可以想象,大型繁忙的服务器上,dump出来的文件该有多大。需要知道的是,dump出来的文件信息是很原始的,绝不适合人直接观看,而jmap-histo显示的内容又太简单,例如只显示某些类型的对象占用多大内存,以及这些对象的数量,但是没有更详细的信息,例如这些对象分别是由谁创建的。那这么说,dump出来的文件有什么用呢?当然有用,因为有专门分析jvm的内存dump文件的工具。
我在本机执行jstat-gcutil34010000,这个命令是每个10秒钟输出一次jvm的gc信息,10000指的是间隔时间为10000毫秒。屏幕上显示如下信息(我只取了第一行,因为是按的一定频率显示,所以实际执行的时候,会有很多行):
S0S1E O PYGCYGCTFGCFGCTGCT
54.62 0.00 42.87 43.52 86.24 17925.093337.670 12.763
额……怎么说呢,要看懂这些信息代表什么意思,还必须对jvm的gc机制有一定的了解才行啊。其实如果对sun的hotspotjvm的gc比较了解的人,应该很容易看懂这些信息,但是不清楚gc机制的人,有点莫名其妙,所以在这里我还是先讲讲sun的jvm的gc机制吧。说到gc,其实不仅仅只是java的概念,其实在java之前,就有很多语言有gc的概念了,gc嘛就是垃圾收集的意思,更多的是一种算法性的东西,而跟具体语言没太大关系,所以关于gc的历史,gc的主流算法我就不讲了,那扯得太远了,扯得太远了就是扯淡。sun现在的jvm,内存的管理模型是分代模型,所以gc当然是分代收集了。分代是什么意思呢?就是将对象按照生命周期分成三个层次,分别是:新生代,旧生代,持久代。对象刚开始分配的时候,大部分都在新生代,当新生代gc提交被触发后了,执行一次新生代范围内的gc,这叫minorgc,如果执行了几次minorgc后,还有对象存活,将这些对象转入旧生代,因为这些对象已经经过了组织的重重考验了哇。旧生代的gc频率会更低一些,如果旧生代执行了gc,那就是fullgc,因为不是局部gc,而是全内存范围的gc,这会造成应用停顿,因为全内存收集,必须封锁内存,不许有新的对象分配到内存,持久代就是一些jvm期间,基本不会消失的对象,例如class的定义,jvm方法区信息,例如静态块。需要主要的是,新生代里又分了三个空间:eden,susvivor0,susvivor1,按字面上来理解,就是伊甸园区,幸存1区,幸存2区。新对象分配在eden区中,eden区满时,采用标记-复制算法,即检查出eden区存活的对象,并将这些对象复制到是s0或s1中,然后清空eden区。jvm的gc说开来,不只是这么简单,例如还有串行收集,并行收集,并发收集,还有着名的火车算法,不过那说得太远了,现在对这个有大致了解就好。说到这里,再来看一下上面输出的信息:
S0 S1 EO P YGCYGCTFGCFGCTGCT
54.62 0.00 42.87 43.52 86.24 17925.093337.670 12.763
S0:新生代的susvivor0区,空间使用率为5462%
S1:新生代的susvivor1区,空间使用率为0.00%(因为还没有执行第二次minor收集)
E:eden区,空间使用率42.87%
O:旧生代,空间使用率43.52%
P:持久带,空间使用率86.24%
YGC:minorgc执行次数1792次
YGCT:minorgc耗费的时间5.093毫秒
FGC:fullgc执行次数33
FGCT:fullgc耗费的时间7.670毫秒
GCT:gc耗费的总时间12.763毫秒
相关文章
- JAVA三元运算符_java中三元运算符详解
- java 104规约_IEC104规约,Java开发主站程序
- 一篇文章弄懂Java多线程基础和Java内存模型
- java传真发送,用Java发送传真解决之道
- java源程序文件扩展名_JAVA源代码的扩展名为( )
- java平均的随机数_Java 随机数详解「建议收藏」
- java获取服务器路径_Java获取此次请求URL以及服务器根路径的方法「建议收藏」
- 【说站】java内存泄漏
- Java重置_java设置定时任务一小时执行一次
- 【JAVA面试必会】JMM高并发详解(java内存模型、JMM三大特征、volatile关键字 )「建议收藏」
- java事务_Java 事务详解[通俗易懂]
- java prototype是什么,Java设计模式之原型模式(Prototype模式)介绍
- Java内存溢出的常见情况和处理方式总结详解架构师
- java压缩与解压(Java.util.zip)详解编程语言
- Java获得jvm占用的内存和系统的可用内存信息详解编程语言
- Java实现一个简单的内存缓存类详解编程语言
- Java学习笔记之四java进制转化详解编程语言
- Java学习笔记之一java关键字及作用详解编程语言
- Java程序员必备知识,《JAVA编程思想》包和访问权限详解编程语言
- eeOracle放弃Java EE:梦想的终结(oracle放弃java)
- Java问题-java进程占用内存过高,排查原因详解编程语言
- Java 虚拟机总结 – JVM 内存区域详解编程语言
- Java编程操作Oracle数据库(java操作oracle)
- 连接高效完成Java面试:掌握Oracle连接知识(java面试oracle)
- 连接MySQL连接技术之Java实现(java的mysql)
- Java如何查询MySQL?25字(java查询mysql)
- Java导出Oracle数据提升数据分析流程效率(java导出oracle)
- 深入分析Java内存区域的使用详解
- 基于Java内存溢出的解决方法详解