Java 内存储器泄露模拟

Java 内存泄露模拟

转:http://my.oschina.net/gofan/blog/73266

 

常见的内存泄露:

1.文件流不关闭

2.数据库连接没有关闭

3.内存使用过多

 

内存不够用如下:

 

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);

                    }

                }

            }

 

如果将程序改为如下,则不会泄露:

 

 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 命令打印如下:


Java 内存储器泄露模拟

 

查看实例如下:

 


Java 内存储器泄露模拟

 

发现有163959432个int的数组;

 

不存在泄露时的截图如下:


Java 内存储器泄露模拟


经对比可发现,内存泄露时E区和old区使用率迅速加大,fgc增多,知道使用为99时报outofmemory错误。

 

常用分析内存泄露问题命令:

jps -l  -v   查看正在运行的进程号

jmap -histo pid 查看pid进程中的实例数

jstat -gcutil pid 3000 每个3秒打印个区中的内存使用状态

jconsole pid 打开jconsole可视化页面查看