java 内存泄漏样例 java中内存泄漏的场景

一、概念

1. 内存泄漏:对象使用完之后,没有按照预期被GC回收,一直留在内存中

2. 内存溢出:大量对象一直留在内存中,导致内存不够用(OOM),影响正常的程序运行

二、内存泄漏的场景

1. 内存中数据量太大,比如一次性从数据库中取出来太多数据;

2. 静态集合类中对对象的引用,在使用完后未清空(只把对象设为null,而不是从集合中移除),使JVM不能回收,即内存泄漏;

3. 静态方法中只能使用全局静态变量,而如果静态变量又持有静态方法传入的参数对象的引用,会引起内存泄漏;

4. 代码中存在死循环,或者循环过多,产生过多的重复的对象;

5. JVM启动参数内存值设置过小

a. 堆内存:JVM默认为64M,-Xms堆的最小值, -Xmx堆的最大值,OutOfMemoryError: java heap space

b. 栈内存:-Xss,StackOverflowError,栈太深

c. 永久代内存:-XX:PermSize,-XX:MaxPermSize,OutOfMemoryError: PermGen space,加载的类过多

6. 监听器:addXXListener,没有remove;

7. 各种连接没有关闭:例如数据库连接、网络连接;

8. 单例模式:如果单例对象持有外部对象的引用,那么外部对象将不会被回收,引起内存泄漏;

9. 一个类含有静态变量,这个类的对象就无法被回收;

10. ThreadLocal;

三、解决思路

1. 修改JVM启动参数,直接增加内存;

2. 检查错误日志;

3. 检查代码中有没有一次性查出数据库所有数据;

4. 检查代码中是否有死循环;

5. 检查代码中循环和递归是否产生大量重复对象;

6. 检查List/Map等集合,是否未清除;

7. 使用内存查看工具;

四、代码优化

1. 主动释放无用的对象;

2. 尽量使用StringBuilder代替String;

3. 尽量少用静态变量,因为静态变量是类的,GC不会回收;

4. 避免创建大对象和同时创建多个对象,例如数组,因为数组的长度是固定的;

5. 对象池技术;

五、举例:

在Java开发中,有一些常见的内存泄漏场景。以下是一些例子: 
1. 静态集合:在静态集合中保持对对象的引用,即使它们不再需要,也会阻止它们被垃圾回收。例如:
public class DataHolder {
    private static List<Data> dataList = new ArrayList<>();
     public static void addData(Data data) {
        dataList.add(data);
    }
}
如果对象被添加到 dataList 中,但从未被移除,它们将在内存中累积,导致内存泄漏。 
 
2. 未关闭的资源:未正确关闭资源,如文件句柄、数据库连接或网络套接字,会导致内存泄漏。例如:
public void readDataFromFile(String filePath) {
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new FileReader(filePath));
        // 从文件中读取数据
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // 缺少close()语句
    }
}
在这个例子中,如果没有在 BufferedReader 对象上调用 close() 方法,将会导致资源泄漏和潜在的内存泄漏。 
 
3. 事件监听器:注册事件监听器但未正确取消注册它们会导致内存泄漏。例如:
public class EventListener {
    public void registerListener() {
        EventManager.getInstance().addListener(this);
    }
     public void deregisterListener() {
        EventManager.getInstance().removeListener(this);
    }
}
如果当监听器不再需要时没有调用 deregisterListener() 方法,它将保留在内存中,阻止垃圾回收。 
 
4. 缓存:错误地缓存对象可能会导致内存泄漏,如果缓存没有得到正确管理。例如:
public class DataCache {
    private static Map<String, Data> cache = new HashMap<>();
     public static void addToCache(String key, Data data) {
        cache.put(key, data);
    }
}
如果对象不断被添加到缓存中而没有被移除或清除,就会导致内存使用过多和潜在的内存泄漏。 
 
这些只是Java开发中常见的一些内存泄漏场景的例子。重要的是要意识到这些情况,并确保在不再需要对象时正确管理和释放它们。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值