JVM内存溢出泄露及相关工具
JVM-内存溢出/泄露及相关工具what
什么是内存溢出和内存泄漏呢? 内存溢出:内存空间不足导致; 内存泄漏:应该释放的对象没有释放。
拿一个生活中的事情来举例:
张三最近交了一个女朋友小红,女孩是他的初恋。张三全心全意地爱惜这个女孩,此时张三心里装不下其他人,这个有另外一个女孩想进入张三内心进不去,这个时候就是内存溢出(张三的心里装满了小红没有空间装下其他女孩)。
小红虽然也喜欢张三,但是心里还有前男友,这个时候小红无法全心全意对张三,这个就是内存泄漏。
show code (展示什么是内存泄漏) public class MemoryLeak { private Object[] eles; private final static int size = 8; private int index; public MemoryLeak() { this.eles = new Object[size]; } // 往数组中放入元素 public void put(Object o){ eles[index] = o; index++; } // 从数组中取出(此方放应该是取出不是复制,方法中故意没有对元素进行置空) public Object take(){ index--; return eles[index]; } public static void main(String[] args) { MemoryLeak ml = new MemoryLeak(); Object o = new Object(); System.out.println(o); ml.put(o); Object to = ml.take(); System.out.println(to); System.out.println("-----------"); } }
下图为运行结果: 可以看到调用完 take之后 ml中数组中仍然是有数据的,这种情况就是内存溢出
tools
这部分不经常使用的话是记不住的,这里就写一个记录方便以后自己查看
JDK为我们提供的工具
名称
作用
jps
虚拟机进程状况工具
jstat
虚拟机统计信息监视工具
jinfo
Java配置信息工具
jmap
Java内存映像工具
jstack
Java堆栈跟踪工具
JConsole
Java监视与管理控制台
VisualVM
多合一故障处理工具 jps
列出当前机器上正在运行的虚拟机进程
-p :仅仅显示VM 表示,不显示jar,class, main参数等信息.
-m:输出主函数传入的参数. 下的hello 就是在执行程序时从命令行输入的参数
-l: 输出应用程序主类完整package名称或jar完整名称.
-v: 列出jvm参数, -Xms20m -Xmx50m是启动程序指定的jvm参数 jstat
是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具。
假设需要每250毫秒查询一次进程91600垃圾收集状况,一共查询20次,那命令应当是:jstat -gc 91600 250 20
S0C 表示 servivor0容量 | S0U 表示 servivor0已用
S1C 表示 servivor1容量 | S1U 表示 servivor1已用
E 伊甸区 O 老年代(C 容量 U 已用)
YGC 年轻代GC YGCT 次数
常用参数: class (类加载器) compiler (JIT) gc (GC堆状态) gccapacity (各区大小) gccause (最近一次GC统计和原因) gcnew (新区统计) gcnewcapacity (新区大小) gcold (老区统计) gcoldcapacity (老区大小) gcpermcapacity (永久区大小) gcutil (GC统计汇总) printcompilation (HotSpot编译统计) jinfo
查看和修改虚拟机的参数
jinfo –sysprops 可以查看由System.getProperties()取得的参数
jinfo –flag 未被显式指定的参数的系统默认值
jinfo –flags(注意s)显示虚拟机的参数
jinfo –flag +[参数] 可以增加参数,但是仅限于由java -XX:+PrintFlagsFinal –version查询出来且为manageable的参数
jinfo –flag -[参数] 可以去除参数
虚拟机参数设置: -XX:+PrintGC public class JinfoDemo { public static void main(String[] args) { while (true){ byte[] b = null; for (int i = 0; i < 10; i++) { b = new byte[1 * 1024 * 1024]; } try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
上述程序查看控制台输出
// 控制台输出 [GC (Allocation Failure) 41912K->2186K(174080K), 0.0005920 secs] [GC (Allocation Failure) 42926K->2186K(172032K), 0.0007325 secs] ...
使用jinfo来修改参数 jinfo -flags 152036(pid可以使用jps命令查看)
这里可以看到设置的虚拟机参数信息
执行命令 jinfo -flag +PrintGCDetails 152036 修改PrintGCDetails参数
修改完后查看控制台输出
[GC (Allocation Failure) [PSYoungGen: 28190K->1024K(29696K)] 29353K->2186K(159744K), 0.0008307 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 28190K->0K(29696K)] 29353K->1162K(159744K), 0.0003659 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] ...
停掉应用重启后发现控制台输出又变回去了。 jmap/jhat
jmap:用于生成堆转储快照(一般称为heapdump或dump文件)。jmap的作用并不仅仅是为了获取dump文件,它还可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。和jinfo命令一样,jmap有不少功能在Windows平台下都是受限的,除了生成dump文件的-dump选项和用于查看每个类的实例、空间占用统计的-histo选项在所有操作系统都提供之外,其余选项都只能在Linux/Solaris下使用。
jmap -dump:live,format=b,file=heap.bin
jhat:jhat dump文件名(jhat尽量不要使用,因为使用起来比较占用资源)
屏幕显示"Server is ready."的提示后,用户在浏览器中键入http://localhost:7000/就可以访问详情
jstack
(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等都是导致线程长时间停顿的常见原因。
在代码中可以用java.lang.Thread类的getAllStackTraces()方法用于获取虚拟机中所有线程的StackTraceElement对象。使用这个方法可以通过简单的几行代码就完成jstack的大部分功能,在实际项目中不妨调用这个方法做个管理员页面,可以随时使用浏览器来查看线程堆栈。 public class JstackDemo { public static void main(String[] args) { while(true){ Map threadMap = Thread.getAllStackTraces(); for(Map.Entry entry: threadMap.entrySet()) { Thread t = entry.getKey(); StackTraceElement[] ss = entry.getValue(); System.out.println(t.getName()+"-"+t.getId()); for(StackTraceElement s:ss) { System.out.println(s); } } } } }JConsole
*管理远程进程需要在远程程序的启动参数中增加:*
-Djava.rmi.server.hostname=…..
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8888
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=falsevisualvm
懒得搞了,以后再补 Mat工具
eclipse memory analyzer
https://www.eclipse.org/mat/downloads.php
*浅堆和深堆*
浅堆 :(Shallow Heap)是指一个对象所消耗的内存。例如,在32位系统中,一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用8个字节。
深堆 :这个对象被GC回收后,可以真实释放的内存大小,也就是只能通过对象被 *直接* 或 *间接* 访问到的所有对象的集合。通俗地说,就是指仅被对象所持有的对象的集合。深堆是指对象的保留集中所有的对象的浅堆大小之和。
举例:对象A引用了C和D,对象B引用了C和E。那么对象A的浅堆大小只是A本身,不含C和D,而A的实际大小为A、C、D三者之和。而A的深堆大小为A与D之和,由于对象C还可以通过对象B访问到,因此不在对象A的深堆范围内。
让网络信号无惧风雨,江苏移动严阵以待迎战烟花自台风烟花登陆以来,对江苏部分地区的影响逐渐显现。中国移动江苏公司(以下简称江苏移动)严阵以待,提前巡查重点场所,梳理防汛物资,时刻跟踪台风路径和相关预警信息,做好24小时防汛值班
常州移动开展系列安心服务营造全民反诈浓厚氛围正值517世界电信日来临之际,常州移动针对当前通讯网络诈骗高发的复杂形势,开展系列安心服务活动,进一步浓厚全民反诈全社会反诈氛围,增强广大人民群众的反诈防骗意识和能力。一方面,常州
口腔护理小帮手联想声波电动牙刷T1每年的9月20日是国际爱牙日,越来越多的人关注牙齿健康。刷牙是我们每天起床必须做的事情,其实晚上也是要刷牙,这样才能保证口腔卫生。三年前笔者开始使用电动牙刷,体验过的人不必多说,能
ZMI紫米PD65W快充头多口适配器开箱评测平时我们在出差或旅游的时候,避免不了要携带各种电子设备,如手机平板相机笔记本游戏机等等,随之而来会有一个小问题,怎么给这些数码设备同时充电。充电器又不能每个都带,可少了又不够用,而
开学季好礼米兔儿童学习手表4X手腕上的学习机前言9月1号这一天朋友圈几乎被孩子上学刷屏了,真是一人开学,全家光荣。对于学生们上学都需要哪些东西呢?现在的儿童都很幸福,除了文具用品外,很多家长也会尝试选择一些电子产品,儿童电话
拖地不再难为宝宝深度清洁全屋飞乐思蒸汽除菌拖把疫情防疫常态化,除了个人做好防护,守护家人健康也是需要我做的。家里自从宝宝会爬了以后,每天都要扫地拖地,而这种日常的家务,也担心传统拖把洗不干净会有细菌,生怕宝宝会生病。所以干净无
小身材大性能没广告泰捷WE40盒子升级版开箱评测还记得多年前家里没有智能电视的时候,为了不办有线电视,就入手了小米盒子,当时也算是新潮,因为可以装软件,电视直播电影大片都是免费看,片源质量也都很好,最经典的要说泰捷视频了,不仅能
保温杯大小的米家随手吸尘器小脏小乱马上吸日常生活中,灰尘随处可见,如在办公室家庭中汽车内的各种物品缝隙中,都会夹杂着灰尘残渣碎发等,要经常定期打扫才行,但普通的吸尘器体积大,对一些犄角旮旯的地方很难清洁,所以我考虑入手个
一只口红大小的口袋云台相机橙影智能摄影机M1前言导读近年来,Vlog逐渐地再全球范围内风靡。伴随着以抖音为代表的短视频平台的崛起,各大平台纷纷推出自己的短视频扶持计划,无论是明星艺人大V网红还是素人都纷纷加入这一行业,也掀起
常州移动烟火预警平台为村民消除安全隐患近日,常州移动为常州市新北区春江街道搭建的烟火预警平台顺利上线,刚上线三天便助力街道排除了一起安全隐患。常州移动积极落实我为群众办实事党史学习教育要求,坚持数智移动实事为民战略定位
创新科携郑州银行开启战略合作近日,深圳创新科与郑州银行本着长期合作相互支持共谋发展的原则签订了战略合作协议。双方将以合作共赢为基础,加强全面合作,发挥各自优势,促进共同发展。根据协议双方将在园区建设融资高科技