java 内存泄露 分析_Java 内存泄漏的分析

主要有以下原因:对象定义在错误的范围

异常处理不当

集合数据管理不当

对象定义在错误的范围

分析下面的代码:

public class Memory {private String[] names;public void handle(int length) {names = new String[length];System.out.println(names);}}

names 仅仅作为简单的使用,仅在 handle 方法中使用,由于 Memory 的实例对象持有 names 对象,只要该实例不被回收,那么names 实例也不会被回收,出现临时性内存泄漏,修改为下面的代码更合适

public class Memory {public void handle(int length) {String[] names = new String[length];System.out.println(names);}}

异常处理不当

public class Memory {public void handle(int length) {InputStream inputStream = null;try {doSomething();inputStream.close();} catch (Exception e) {// 若doSomething 出现内存泄漏,会导致close方法不会正常被调用// 导致inputStream 不会被正确回收,导致内存泄漏}}}

集合数据处理不当

基于数组的结构,尽量减少resize , 因为 resize的时候会涉及到数据拷贝,以及内存碎片的问题

如果集合只需要顺序访问,而非随机访问,可以使用LinkedList 代替ArrayList ,因为链表不需要resize

ThreadLocal使用不当

在线程池中使用ThreadLocal的时候要特别注意,在用完之后一定要手动的移除,否则可能造成内存泄漏,可以查看下面的代码

public static void main(String[] args) {sleep(10_000);ExecutorService executorService = Executors.newFixedThreadPool(1);executorService.submit(() -> {ThreadLocal f = new ThreadLocal<>();f.set(new byte[30 * 1024 * 1024]);sleep(1_000);f.remove(); ## 手动移除System.out.println("任务执行完。。。。");});sleep(3_000);System.out.println("执行GC2");System.gc();sleep(10_000);}

这是由于线程池执行任务的时候,复用线程,当在任务中设置ThreadLocal的时候,其实是为某个线程设置ThreadLocl,所以如果此线程不关闭,那么则线程会一直持有此对象,造成内存泄漏,无法回收! 更多关于线程池,ThreadLocal的知识,可以查看笔者的 多线程的应用-异步任务线程池的简单实现 这篇博文,通过实现一个简单的线程池来学些线程池的相关知识。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值