内存溢出与内存泄漏区别

Java内存泄漏就是没有及时清理内存垃圾,导致系统无法再给你提供内存资源(内存资源耗尽);

而Java内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。

内存溢出,这个好理解,说明存储空间不够大。就像倒水倒多了,从杯子上面溢出了来了一样。
内存泄漏,原理是,使用过的内存空间没有被及时释放,长时间占用内存,最终导致内存空间不足,而出现内存溢出。

内存泄漏包含内存溢出 

用static时候 会引发这个问题哦 还有IO流问题

 

 

举个栗子:

bean:

public class ReflectPoint {
    public   int x;
    public   int y;

    public ReflectPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

}

 

测试:

存进去对象后,修改属性的值。修改完毕后remove

 

注意对于List的存储

 引用的存储:

   

顺序存储

 

好多个引用变量引用的同一个对象

 

 

 Set的存储:

  存储的时候,先进行比价。如果有了就不存储了。引用都是相等的就不放啦~ 如果希望相等就重写equals方法

 

 

 

补充HashCode方法与HashSet类

 如果想查找一个集合汇总是否包含某个对象,大概的程序代码是这样呢? 你通常是逐一取出每个元素与要查找的对象进行比较,当发现某个元素与要查找的对象进行equals方法比较的结果相等时,则停止继续查找并返回肯定的信息。如果一个集合中有很多元素,注意比较非常恐怖。

 有人发明了哈希算法来提高从集合中查找元素的效率。这种方式将集合分成若干个存储区域,每个对象可以计算进出一个哈希值,可以通过哈希值进行分组,每个分组对应某个存储区域,根据一个对象的哈希值就可以确定该对象应该存储在哪个区域。

  

    HashSet就是采用哈希算法存取对象的集合,它内部采用对某个数字n进行取余数的方式对哈希值进行分组和划分对象的存储区域。Object类中定义了一个hashCode()方法来返回每个Java对象的哈希值。当从HashSet集合中查找某个对象时候,Java系统首先调用对象的hashCode()方法获取该对象的哈希值。然后根据哈希值找到相应存储区域。最后去除该存储区域内的每个元素与该对象进行equals比较。这样就不用遍集合中的所有元素就可以得到结论。可见HashSet集合具有很好的对象检索性能。

 

注意啊 当一个对象被存储近HashSet集合以后,就不要修改这个对象那些参与计算哈希值的字段了,否则对象修改后哈希值与最初存储近HashSet集合中时的哈希值就不同了,在这种情况下,即使contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果。这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露

 

Bean:

package com.toov5.test;

import java.util.Objects;

public class ReflectPoint {
    public   int x;
    public   int y;

    public ReflectPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ReflectPoint that = (ReflectPoint) o;
        return x == that.x &&
                y == that.y;
    }

    @Override
    public int hashCode() {

        return Objects.hash(x, y);
    }
}

测试:

public class test1 {
    public static void main(String[] args) {
        Collection collection = new HashSet<ReflectPoint>();
        ReflectPoint reflectPoint1 = new ReflectPoint(1, 2);
        ReflectPoint reflectPoint2 = new ReflectPoint(3, 4);
        ReflectPoint reflectPoint3 = new ReflectPoint(1, 2);
        collection.add(reflectPoint1);
        collection.add(reflectPoint2);
        collection.add(reflectPoint3);
//        reflectPoint1.y=7;   //修改完后哈希值就改了
        collection.remove(reflectPoint1);
        System.out.println(collection.size());
        System.out.println(collection);
    }
}

结果:

 

 修改参数hashCode的属性值:

public class test1 {
    public static void main(String[] args) {
        Collection collection = new HashSet<ReflectPoint>();
        ReflectPoint reflectPoint1 = new ReflectPoint(1, 2);
        ReflectPoint reflectPoint2 = new ReflectPoint(3, 4);
        ReflectPoint reflectPoint3 = new ReflectPoint(1, 2);
        collection.add(reflectPoint1);
        collection.add(reflectPoint2);
        collection.add(reflectPoint3);
        reflectPoint1.y=7;   //修改完后哈希值就改了
        collection.remove(reflectPoint1);
        System.out.println(collection.size());
        System.out.println(collection);
    }
}

运行结果:

 

 这样频繁的操作,有些对象删除不掉,会造成内存泄露哦。哈希值在某个区域里面。以为删掉了~~

对象不用了却一直在,占用着内存空间。

 

posted @ 2018-10-30 00:34  toov5  阅读(500)  评论(0编辑  收藏  举报