ThreadLocal,gc后ThreadLocal为什么没有被回收?

叫练 2021-03-19 05:58:16
/**
* ThreadLocal 不支持继承
* add by duyang 2019 06 28
*/
public class ThreadLocalTest {


/**
* InheritableThreadLocal 子线程可以访问父线程变量;
*/
//private static ThreadLocal<String> localVariable = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
ThreadLocal<String> localVariable = new ThreadLocal<>();
localVariable.set("叫练");
System.gc();
System.out.println(Thread.currentThread()+" "+ localVariable.get());
//删除ThreadLocal
//localVariable.remove();
}
}


第16行代码怎么还有值,说明GC没有回收ThreadLocal?有大神来吗
...全文
1589 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhouhangzhouxing 2021-08-19
  • 打赏
  • 举报
回复

12到19行在同一个栈帧里。还没跑完呢 为啥要回收 可达性分析法 栈帧中的局部变量可以作为GC Roots 只要当这个方法出栈的时候才会回收。

冰思雨 2021-04-08
  • 打赏
  • 举报
回复
引用 楼主 叫练 的回复:
/**
 * ThreadLocal 不支持继承
 * add by duyang 2019 06 28
 */
public class ThreadLocalTest {


    /**
     * InheritableThreadLocal 子线程可以访问父线程变量;
     */
    //private static ThreadLocal<String> localVariable = new ThreadLocal<>();
    public static void main(String[] args) throws InterruptedException {
        ThreadLocal<String> localVariable = new ThreadLocal<>();
        localVariable.set("叫练");
        System.gc();
        System.out.println(Thread.currentThread()+" "+ localVariable.get());
        //删除ThreadLocal
        //localVariable.remove();
    }
}
第16行代码怎么还有值,说明GC没有回收ThreadLocal?有大神来吗
从两个角度来看这个问题: 1. 方法体内的局部变量的生命周期: 方法体内的局部变量,在方法返回之后,或者显式的赋值为null时,才有可能被垃圾回收, 楼主在main方法体中声明的变量,没有显式的赋值为null,所以,在main方法没有返回之前,该变量是不可能被回收的(无论它是否为线程本地变量)。 2. 线程本地变量的声明周期: 线程本地变量的生命周期覆盖了当前线程的声明周期,也就是说,线程本地变量,在当前线程使用了之后,只要当前线程没有结束(run/main方法没有返回或者抛出异常),线程本地变量中引用的对象就不会被垃圾回收。 从这两个角度都可以解释楼主的问题,但是,一般情况下,我们关注的是第二个角度。
叫练 2021-03-25
  • 打赏
  • 举报
回复
引用 9 楼 rumlee 的回复:
ThreadLocal保存的数据,实际上是通过2个引用可达,一个是ThreadLocal的弱引用,还有一个是当前线程的强引用。你这里当前线程并未结束,而且ThreadLocal对象也是在引用有效范围之内,当然不可能回收。 ThreadLocal中的Entry之所以设计成弱引用,目的是为了解决线程执行结束了,而ThreadLocal对象的内存泄漏问题。
最后一句很精辟!
KeepSayingNo 2021-03-25
  • 打赏
  • 举报
回复
ThreadLocal 一般用也不会直接定义在方法体中,都是定义到类中,跟随类的生成周期
乔不思 2021-03-24
  • 打赏
  • 举报
回复
引用 3 楼 乔不思 的回复:
方法执行完会自动回收,但是threadLocal存在弱引用还是得手动清除一下才能把真正内存释放,不然会内存泄漏导致内存溢出。
补充: 方法执行完 虚拟机方法栈中的引用才会被回收,根据标记的可达性算法追溯才有可能让堆中的ThreadLocal对象和ThreadLocalMap和EntryMap对象被回收。前提是方法得执行完。
rumlee 2021-03-24
  • 打赏
  • 举报
回复
ThreadLocal保存的数据,实际上是通过2个引用可达,一个是ThreadLocal的弱引用,还有一个是当前线程的强引用。你这里当前线程并未结束,而且ThreadLocal对象也是在引用有效范围之内,当然不可能回收。 ThreadLocal中的Entry之所以设计成弱引用,目的是为了解决线程执行结束了,而ThreadLocal对象的内存泄漏问题。
wscxyey 2023-08-28
  • 举报
回复
@rumlee 瞎扯淡!方法栈中的ThreadLocal 才是强引用,有强引用存在gc是不会被回收的。方法执行完后强引用释放剩下线程的弱引用gc 就可以回收了
叫练 2021-03-24
  • 打赏
  • 举报
回复
引用 3 楼 乔不思 的回复:
方法执行完会自动回收,但是threadLocal存在弱引用还是得手动清除一下才能把真正内存释放,不然会内存泄漏导致内存溢出。
刚看第一句话,我觉得是有问题的,因为value可能被引用,完全回收?肯定是不可能的,后面说的就有道理了!
叫练 2021-03-24
  • 打赏
  • 举报
回复
引用 5 楼 乔不思 的回复:
[quote=引用 3 楼 乔不思 的回复:]方法执行完会自动回收,但是threadLocal存在弱引用还是得手动清除一下才能把真正内存释放,不然会内存泄漏导致内存溢出。
补充: 方法执行完 虚拟机方法栈中的引用才会被回收,根据标记的可达性算法追溯才有可能让堆中的ThreadLocal对象和ThreadLocalMap和EntryMap对象被回收。前提是方法得执行完。[/quote] 感谢大佬们的帮助!
乔不思 2021-03-24
  • 打赏
  • 举报
回复
结贴吧
北落师门_Orz 2021-03-23
  • 打赏
  • 举报
回复
你这个对象还没有离开方法体把,对象相当于还被引用
rumlee 2021-03-22
  • 打赏
  • 举报
回复
且不说System.gc靠不靠谱 localVariable是一个强引用的对象,而且还在有效作用域范围之内,就是说对象还存在有效强引用的情况下,如果这样都回收的话,你的程序岂不是要崩溃啊。
乔不思 2021-03-22
  • 打赏
  • 举报
回复
方法执行完会自动回收,但是threadLocal存在弱引用还是得手动清除一下才能把真正内存释放,不然会内存泄漏导致内存溢出。
立青_ 2021-03-19
  • 打赏
  • 举报
回复
执行System.gc()函数的作用只是提醒或告诉虚拟机,希望进行一次垃圾回收。至于什么时候进行回收还是取决于虚拟机,而且也不能保证一定进行回收

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧