对ThreadLocal内存泄漏及弱引用的理解

 更新时间:2022年01月29日 11:19:12   作者:Burton_J  
这篇文章主要介绍了对ThreadLocal内存泄漏及弱引用的理解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

ThreadLocal内存泄漏及弱引用

1.什么是内存泄漏?Entry的key弱引用与泄漏关系

在TreadLocal中内存泄漏是指TreadLocalMap中的Entry中的key为null,而value不为null。因为key为null导致value一直访问不到,而根据可达性分析,始终有threadRef->currentThread->threadLocalMap->entry->valueRef->valueMemory,导致在垃圾回收的时候进行可达性分析的时候,value可达从而不会被回收掉,但是该value永远不能被访问到,这样就存在了内存泄漏。

因为Entry的key是弱引用,所以在gc的时候key会被回收,而value是强引用,导致value不会被回收。

如果不使用弱引用也会可能会发生内存泄漏,只要在业务代码里,将ThreadLocal的引用置为null,也会导致Entry中value访问不到,但又因为可达,所以gc时候不会被回收,相当于这部分内存资源被浪费了

2.为什么Entry的key使用弱引用

假设threadLocal使用的是强引用,在业务代码中执行threadLocal Instance=null操作,以清理掉threadLocal实例的目的,但是因为threadLocalMap的Entry强引用threadLocal,因此在gc的时候进行可达性分析,threadLocal依然可达,对threadLocal并不会进行垃圾回收,这样就无法真正达到业务逻辑的目的,出现逻辑错误。

假设Entry弱引用threadLocal,尽管会出现内存泄漏的问题,但是在threadLocal的生命周期里(set,getEntry,remove)里,都会针对key为null的脏entry进行处理。

3.预防内存泄漏

ThreadLocal源码中其实已经对内存泄漏问题做了很多优化,在set,get,remove方法中都会对key为null的但是value不为null的Entry进行value置null操作,使得value的引用为null,可达性失败,在gc是可以回收value的内存。

在日常使用中,最后用完TreadLocal后,记得remove,为什么呢?

因为如果不remove,当一次gc执行,这个value就会造成内存泄漏直到当前线程结束(线程结束,ThreaLocalMap会被置为null,而ThreaLocalMap中的Entry自己也就不可达,会被回收,一切都被回收)

线程结束时会执行Thread.exit方法

private void exit() {
    if (group != null) {
        group.threadTerminated(this);
        group = null;
    }
    /* Aggressively null out all reference fields: see bug 4006245 */
    target = null;
    /* Speed the release of some of these resources */
    threadLocals = null;
    inheritableThreadLocals = null;
    inheritedAccessControlContext = null;
    blocker = null;
    uncaughtExceptionHandler = null;
}

匿名内部类会导致内存泄露

内存泄露:就是本该被GC回收的对象,因为各种原因导致的无法被回收,造成内存资源的浪费,从而导致OOM。

如果一个类使用了内部类,而两个类的生命周期不一致,比如内部类的生命周期比外部类生命周期长,

这就会导致外部类的生命周期结束了,本该被回收的,却因为内部类会隐式强引用外部类,所以导致外部类无法被回收,

从而造成了内存泄露。

解决方案

1. 可以避免使用内部类;

2. 内部类可以用弱引用来引用外部类;

3. 使用静态内部类,静态内部类不持有外部类的引用(如果要调用外部类方法或使用外部类属性,可以使用弱引用来解决)。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java 文件上传到读取文件内容的实例

    java 文件上传到读取文件内容的实例

    今天小编就为大家分享一篇java 文件上传到读取文件内容的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 一文总结 Shiro 实战教程

    一文总结 Shiro 实战教程

    shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权,这篇文章详细总结了shiro用法,感兴趣的同学可以参考阅读
    2023-04-04
  • Java代理的几种实现方式总结

    Java代理的几种实现方式总结

    本文将通过例子说明java代理的几种实现方式,并比较它们之间的差异,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的参考价值,需要的朋友可以参考下
    2023-12-12
  • 教你使用springSecurity+jwt实现互踢功能

    教你使用springSecurity+jwt实现互踢功能

    JWT作为一个开放的标准( RFC 7519 ),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。接下来通过本文给大家介绍springSecurity+jwt实现互踢功能,需要的朋友可以参考下
    2021-11-11
  • Java使用synchronized实现互斥锁功能示例

    Java使用synchronized实现互斥锁功能示例

    这篇文章主要介绍了Java使用synchronized实现互斥锁功能,结合实例形式分析了Java使用synchronized互斥锁功能简单实现方法与操作技巧,需要的朋友可以参考下
    2020-05-05
  • javafx实现图片3D翻转效果方法实例

    javafx实现图片3D翻转效果方法实例

    程序实现思路: 在javafx中Node对象有一个effect属性,可以用于实现各种特效。PerspectiveTransform特效可以使Node对象实现透视变换。因此我们可以通过计算透视变换中每个点的位置来实现3D翻转特效。
    2013-04-04
  • POI导出之Excel实现单元格的背景色填充问题

    POI导出之Excel实现单元格的背景色填充问题

    这篇文章主要介绍了POI导出之Excel实现单元格的背景色填充问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • java  基础知识之IO总结

    java 基础知识之IO总结

    这篇文章主要介绍了java 基础知识之IO总结的相关资料,Java中的I/O分为两种类型,一种是顺序读取,一种是随机读取,需要的朋友可以参考下
    2017-03-03
  • 推荐几本学习java的书籍

    推荐几本学习java的书籍

    本文给大家推荐了几本学习Java的书籍,非常适合Java的初学者,有需要的朋友可以看看
    2014-10-10
  • 使用Java编写控制JDBC连接、执行及关闭的工具类

    使用Java编写控制JDBC连接、执行及关闭的工具类

    这篇文章主要介绍了如何使用Java来编写控制JDBC连接、执行及关闭的程序,包括一个针对各种数据库通用的释放资源的工具类的写法,需要的朋友可以参考下
    2016-03-03

最新评论