张三最近交了一个女朋友小红,女孩是他的初恋。张三全心全意地爱惜这个女孩,此时张三心里装不下其他人,这个有其余一个女孩想进入张三内心进不去,这个时候便是内存溢出(张三的心里装满了小红没有空间装下其他女孩)。
小红虽然也喜好张三,但是心里还有前男友,这个时候小红无法全心全意对张三,这个便是内存泄露。
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/jhatjmap:用于天生堆转储快照(一样平常称为heapdump或dump文件)。jmap的浸染并不仅仅是为了获取dump文件,它还可以查询finalize实行行列步队、Java堆和永久代的详细信息,如空间利用率、当前用的是哪种网络器等。和jinfo命令一样,jmap有不少功能在Windows平台下都是受限的,除了天生dump文件的-dump选项和用于查看每个类的实例、空间占用统计的-histo选项在所有操作系统都供应之外,别的选项都只能在Linux/Solaris下利用。
jmap -dump:live,format=b,file=heap.bin <pid>
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<Thread, StackTraceElement[]> threadMap = Thread.getAllStackTraces(); for(Map.Entry<Thread, StackTraceElement[]> 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=false
visualvmMat工具
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的深堆范围内。