【问题标题】:Could finally block get skipped due to GC in a threaded situation?由于 GC 在线程情况下最终会被跳过吗?
【发布时间】:2013-11-04 06:40:06
【问题描述】:

说(可能在单独的线程上)我正在运行一些方法 ClassA.foobar()。 该方法内部是一个 try, (可能是 catch), finally 块。

现在,如果在执行仍在 try 块(或 catch 块)中间时丢失了对该 ClassA 对象(或该线程)的最后引用,该对象(/线程)是否可以被垃圾回收?在我到达finally块之前?换句话说:即使内存中没有对对象(/线程)的强引用,finally 块是否仍然保证运行?

(我不知道 GC 是如何处理孤立的活动线程的。)

虚拟示例:

[Some context]
{
    ClassA classA = new ClassA();
     //Point is this instance and a reference to it exists

    class ClassA
    {
        public void foobar()
        {
            try
            {
                classA = null;
                 //Point is that the last reference to this instance is lost,
                 //and that this happens at this point in foobar() execution.
                 //The actual location of this line of code is irrelevant.
            }
            finally
            {
                //some important stuff here!
            }
        }
    }
}

【问题讨论】:

  • 但最后一个引用没有丢失——this 仍然存在并指向该对象。而且,this 引用绝对可以从 GC 根(即线程)访问,因为它位于线程的堆栈帧上。换句话说,没有所谓的“孤立的活动线程”这样的东西,因为线程本身就是阻止某些东西被 GC 的东西(特别是,如果一个线程知道该对象)。所以,简而言之不是:finally总是被调用。
  • 为了完整起见,我想在一个类似的问题上添加一个链接到此评论,我发现该问题提供了丰富的信息:link(它提到了 finally 块不运行的贬低案例。)
  • 是的,如果您调用System.exit 或强制终止Java 进程(例如,在Linux 上使用kill -9),它也不会运行。

标签: java garbage-collection thread-safety try-catch-finally finally


【解决方案1】:

换句话说:即使内存中没有对对象(/线程)的强引用,finally 块是否仍然保证运行?

是的。 finally 块不会像那样被跳过 - 任何其他代码也不会。

执行线程不是垃圾回收意义上的对象。区分线程本身和代表它的java.lang.Thread 对象很重要——尽管我认为Thread 对象在线程终止之前也不会被垃圾回收。

特别是,完全有可能在系统中没有对可运行对象或其他任何东西的引用的线程,并且线程可以继续运行。例如:

new Thread(new Runnable() {
    @Override public void run() {
        for (int i = 0; i < 1000; i++) {
             System.out.println(i);
        }
    }
}).start();

线程启动后,调用代码不再引用创建的匿名类的实例或Thread 对象 - 但它仍会打印所有 1000 个数字。

【讨论】:

  • 这基本上意味着很有可能“泄露”我认为的线程?我不认为一旦你丢失了一个线程的引用,有什么方法可以找回它? (编辑:看起来像那个例子的代码被认为是坏的吗?)
  • @AnorZaken:不一定。 “一劳永逸”线程可能很有用 - 您不不想必须专门照顾每个线程。尽管经常使用线程池(例如通过执行器服务)是一个更好的主意。
  • 对当前线程的句柄对象的引用总是作为Thread.currentThread()可用的,这证明在JVM的某处,该引用被保留了。
  • @MarkoTopolnik:好吧,我不会让它通过 JVM 来确定没有可能的代码路径仍然可以使用它......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多