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 命令打印如下:
查看实例如下:
发现有163959432个int的数组;
不存在泄露时的截图如下:
经对比可发现,内存泄露时E区和old区使用率迅速加大,fgc增多,知道使用为99时报outofmemory错误。
常用分析内存泄露问题命令:
jps -l -v 查看正在运行的进程号
jmap -histo pid 查看pid进程中的实例数
jstat -gcutil pid 3000 每个3秒打印个区中的内存使用状态
jconsole pid 打开jconsole可视化页面查看