Java 内存泄露模拟
转:http://my.oschina.net/gofan/blog/73266
?
常见的内存泄露:
1.文件流不关闭
2.数据库连接没有关闭
3.内存使用过多
?
内存不够用如下:
? ? ? ? ? ? ? ? ? ? ? ? System.out.print("已分配内存=" + run.totalMemory() /1024 / 1024 + "M,");
? ? ? ? ? ? ? ? ? ? ? ? System.out.print("剩余空间内存=" + run.freeMemory() / 1024 / 1024 + "M");
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("最大可用内存=" + ( run.maxMemory() - run.totalMemory() + run.freeMemory() ) / 1024 / 1024 + "M");
? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(6*1000L);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
?
如果将程序改为如下,则不会泄露:
?
?public static void main(String[] args) throws InterruptedException {
// ? ? ? ? ? ? ? ?List<int[]> list = new ArrayList<int[]>();
? ? ? ? ? ? ? ? Runtime run = Runtime.getRuntime();
? ? ? ? ? ? ? ? int i=1;
? ? ? ? ? ? ? ? while(true){
? ? ? ? ? ? ? ? ? ? int[] arr = new int[1024 * 8];
// ? ? ? ? ? ? ? ? ? ?list.add(arr);
? ? ? ? ? ? ? ? ? ? if(i++ % 1000 == 0 ){
? ? ? ? ? ? ? ? ? ? ? ? System.out.print("i="+i );
? ? ? ? ? ? ? ? ? ? ? ? System.out.print("最大内存=" + run.maxMemory() / 1024 / 1024 + "M,");
? ? ? ? ? ? ? ? ? ? ? ? System.out.print("已分配内存=" + run.totalMemory() /1024 / 1024 + "M,");
? ? ? ? ? ? ? ? ? ? ? ? System.out.print("剩余空间内存=" + run.freeMemory() / 1024 / 1024 + "M");
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("最大可用内存=" + ( run.maxMemory() - run.totalMemory() + run.freeMemory() ) / 1024 / 1024 + "M");
? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(6*1000L);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
所以,当短生存期对象(int[] arr)被长生存期对象(List<int[]> list?)引用时容易出现内存泄露;
即使在原程序中将arr=null,也不能释放掉,应为任然被list引用着。
?
运行内存泄露的程序,用jstat -gcutil 命令打印如下:
?
查看实例如下:
?
?
发现有163959432个int的数组;
?
不存在泄露时的截图如下:
经对比可发现,内存泄露时E区和old区使用率迅速加大,fgc增多,知道使用为99时报outofmemory错误。
?
常用分析内存泄露问题命令:
jps -l ?-v ? 查看正在运行的进程号
jmap -histo pid 查看pid进程中的实例数
jstat -gcutil pid 3000 每个3秒打印个区中的内存使用状态
jconsole pid 打开jconsole可视化页面查看