内存溢出,main线程与虚拟机的关系猜测,待验证

今天学习内存溢出的问题 涉及到一个博客

http://blog.csdn.net/seelye/article/details/8269705

内的第二个例子验证有误,具体如下:

public class testset {
//这个测试可以看出其实是通过引用判断
public static void main(String[] args) 

Set<Person> set = new HashSet<Person>(); 
Person p1 = new Person("唐僧","pwd1",25); 
Person p2 = new Person("孙悟空","pwd2",26); 
Person p3 = new Person("猪八戒","pwd3",27); 
set.add(p1); 
set.add(p2); 
set.add(p3); 
Person p4 = new Person("猪八戒","pwd3",27);
set.add(p4); 
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素! 
p3.setAge(2); //
set.remove(p3); //

System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素! 


set.add(p3); //重新添加,居然添加成功 
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素! 
for (Person person : set) 

System.out.println(person.toString()); 

}
}

这里我推断key的保存原理是根据对于对象的引用

查看hashset源代码

    public boolean add(Object obj)
    {
        return map.put(obj, PRESENT) == null;
    }

    public boolean remove(Object obj)
    {
        return map.remove(obj) == PRESENT;
    }

这里present 为一个静态的object  用于存放每一个要操作的对象

所以remove方法前后随意改变对象的属性,只要引用不改变就每问题

如果创建一个新的对象和原来某个对象所有属性一样,此时remove返回false,证明引用



然后关于第一种说法的内存溢出

1、静态集合类引起内存泄露: 
像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。 

测试如下:

public static void main(String[] args) 

Map<Integer, Person> map=new HashMap<Integer, Person>();

for (int i = 0; i < 100000000; i++) {
Person p=new Person();
map.put(i, p);

                p=null;
}

}

之后观察内存发现内存持续走高,验证成功

然后我想如果增加到某一个状态,让线程等待一下会不会调用gc来回收,于是做以下测试

public static void main(String[] args) throws InterruptedException 

Map<Integer, Person> map=new HashMap<Integer, Person>();

for (int i = 0; i < 100000000; i++) {
Person p=new Person();
map.put(i, p);
p=null;
if (i==20000000) {
map=null;
break;
}
}
System.out.println("完毕");
map=null;
Thread.currentThread().sleep(50000);

}

发现等待的50s里面gc并没有回收这个map,于是继续做测试。


public static void main(String[] args) throws InterruptedException 

Map<Integer, Person> map=new HashMap<Integer, Person>();

for (int i = 0; i < 100000000; i++) {
Person p=new Person();
map.put(i, p);
p=null;
if (i==20000000) {
map=null;
break;
}
}
System.out.println("完毕");
map=null;
Map<Integer, Person> map2=new HashMap<Integer, Person>();

for (int i = 0; i < 100000000; i++) {
Person p=new Person();
map2.put(i, p);
p=null;
if (i==20000000) {
map2=null;
break;
}
}

System.out.println("完毕");

}

第一个完成后内存7.7g,第二个完成后内存居然差不多也是8.多个g

把后面的20000000改成30000000.

此时得到了一个惊呆我的发现

我的电脑初始为5.7g,当达到7.7g时完成第一个循环,第二个循环开始后前大段时间居然内存没啥变多,也就多了100兆左右。后半段增加到8g多

然后我就有两个猜测,第一个是这么多个循环的时候,person对象是复用的

第二个猜测是gc是逐渐进行内存销毁的,于是我打开jvisualvm一探究竟


以为主线程sleep gc会停止  然后看了下下面的说法

http://bbs.csdn.net/topics/390219766     说明main sleep的时候并没有gc

public static void main(String[] args) throws InterruptedException 

Map<Integer, Person> map=new HashMap<Integer, Person>();

for (int i = 0; i < 100000000; i++) {
Person p=new Person();
map.put(i, p);
p=null;
if (i==20000000) {
break;
}
}
System.out.println("完毕");
map=null;
System.gc();
Thread.currentThread().sleep(100000);
Map<Integer, Person> map2=new HashMap<Integer, Person>();

for (int i = 0; i < 100000000; i++) {
// Person p=new Person();
// map2.put(i, p);
// p=null;
// if (i==30000000) {
// break;
// }
}
System.out.println("完毕");}

改成这样,发现内存还是占用的,然后我想到了,会不会main就是jvm的线程导致他不会执行gc,这只是我的猜测。之后验证

然后进入了jvm学习阶段。。

http://www.cnblogs.com/qmfsun/p/5479231.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值