Java中的内存泄露(面试)

内存泄露概念

内存泄露就是堆内存中不再使用的对象在垃圾回收期无法从被回收。因为这些对象仍然存在着引用,所以垃圾收集器不会回收。

内存泄露的症状:

应用程序长时间连续运行时性能严重下降;

应用程序中的OutOfMemoryError堆错误;

自发且奇怪的应用程序崩溃;

Java中内存泄露类型

  1. static字段引起的内存泄露

    大量使用static字段会潜在的导致内存泄露,在Java中,静态字段通常拥有与整个应用程序相匹配的生命周期。

    解决办法:最大限度的减少静态变量的使用;单例模式时,依赖于延迟加载对象而不是立即加载方式。

  2. 未关闭的资源导致内存泄露

    每当创建连接或者打开流时,JVM都会为这些资源分配内存。如果没有关闭连接,会导致持续占有内存。在任意情况下,资源留下的开放连接都会消耗内存,如果我们不处理,就会降低性能,甚至OOM。

    解决办法:使用finally块关闭资源;关闭资源的代码,不应该有异常;jdk1.7后,可以使用try-with-resource块。

  3. 不正确的equals()和hashCode()

    在HashMap和HashSet这种集合中,常常用到equal()和hashCode()来比较对象,如果重写不合理,将会成为潜在的内存泄露问题。

    解决办法:用最佳的方式重写equals()和hashCode。

  4. 引用了外部类的内部类

    非静态内部内的初始化,总是需要外部类的实例;默认情况下,每个非静态内部类都包含对其包含内的隐式引用,如果我们在应用程序中使用这个内部类对象,那么即使在我们的包含类对象超出范围后,它也不会被垃圾收集。

    解决办法:如果内部类不需要访问包含的类成员,考虑转换为静态类。

  5. finalize()方法造成的内存泄露

    重写finalize()方法时,该类的对象不会立即被垃圾收集器收集,如果finalize()方法的代码有问题,那么会潜在的引发OOM;

    解决办法:避免重写finalize()。

  6. 常量字符串造成的内存泄露

    如果我们读取一个很大的String对象,并调用了inter(),那么它将放到字符串池中,位于PermGen中,只要应用程序运行,该字符串就会保留,这就会占用内存,可能造成OOM。

    解决办法:增加PermGen的大小,-XX:MaxPermSize=512m;升级Java版本,JDK1.7后字符串池转移到了堆中。

  7. 使用ThreadLocal造成内存泄露

    一旦线程不再存在,ThreadLocals就应该被垃圾收集,而现在线程的创建都是使用线程池,线程池有线程重用的功能,因此线程就不会被垃圾回收器回收。所以使用到ThreadLocals来保留线程池中线程的变量副本时,ThreadLocals没有显示的删除时,就会一直保留在内存中,不会被垃圾回收。

    解决办法:不在使用ThreadLocal时,调用remove()方法,该方法删除了此变量的当前线程值。不要使用ThreadLocal.set(null),它只是查找与当前线程关联的Map并将键设置为null。

    ThreadLocal
    
    public void remove() {
    
    ThreadLocalMap m = getMap(Thread.currentThread());
    
    if (m != null)
    
        m.remove(this);
    
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值