【问题标题】:Detect Who Created a Thread (w. Eclipse)检测谁创建了线程(使用 Eclipse)
【发布时间】:2010-11-16 16:05:10
【问题描述】:

如何找出谁在 Java 中创建了线程?

想象一下:您在复杂的插件环境中使用了大约 30 个第三方 JAR。你启动它,运行大量代码,进行一些计算,最后调用shutdown()。

这个生命周期通常运行良好,除了在每次运行时一些(非守护进程)线程仍然悬空。如果每次关机都是最后一次关机,这不会有问题,在这种情况下我可以简单地运行 System.exit() 。但是,这个循环可能会运行多次,并且每次通过都会产生更多的垃圾。

那么,我该怎么办?我在 Eclipse 的调试视图中看到了线程。我看到了他们的堆栈跟踪,但他们不包含任何关于其来源的提示。没有创建者的堆栈跟踪,没有可区分的类名,什么都没有。

有人知道如何解决这个问题吗?

【问题讨论】:

标签: java multithreading eclipse stack-trace


【解决方案1】:

好的,我能够自己解决(某种程度上)问题:我在

中设置了一个断点
Thread.start() 

并手动逐步执行每个调用。通过这种方式,我很快发现 Class.forName() 初始化了许多静态代码,这些代码反过来又创建了这些神秘的线程。

虽然我能够解决我的问题,但我仍然认为更一般的任务仍未解决。

【讨论】:

    【解决方案2】:

    我虔诚地命名我的线程(例如使用Thread(Runnable, String)),否则它们最终会得到一个通用且有点无用的名称。转储线程将突出显示正在运行的内容以及(因此)创建它们的内容。这并不能解决第 3 方线程创建问题,我很感激。

    编辑:JavaSpecialist 时事通讯最近(2015 年 2 月)通过使用安全管理器解决了这个问题。见here for more details

    更多:使用 JavaSpecialist 技术的一些细节:SecurityManager API 包括在线程创建者的线程上调用的“checkAccess(newThreadBeingCreated)”。新线程已经初始化了它的“名称”。因此,在该方法中,您可以访问线程创建者的线程和新线程,并且可以记录/打印等。当我尝试这样做时,被监控的代码开始抛出访问保护异常;我通过在 AccessController.doPriviledged(new PrivilegedAction() { ... } 下调用它来解决这个问题,其中 run() 方法调用了被监控的代码。

    【讨论】:

      【解决方案3】:

      在调试 Eclipse 应用程序时,您可以通过单击调试视图中的 org.eclipse.equinox.launcher.Main 字段来停止所有线程。

      然后从那里,对于每个线程,您可以看到堆栈跟踪并继续运行 thred run 方法。

      有时这会有所帮助,有时则无济于事。

      正如 Brian 所说,命名线程是一种很好的做法,因为这是轻松识别“谁创建它们”的唯一方法

      【讨论】:

      • 正如我已经说过的那样,我这样做了,在这种情况下没有任何帮助。我再说一遍:我没有创建这些线程。
      • 正如我所说,我认为名称是唯一的快速解决方案。由于这些线程的“创建者”没有命名它,我认为您提到的解决方案(调试 Thread.start())是唯一的....
      【解决方案4】:

      不幸的是,它没有。在 Eclipse 中,我看到了所有阻塞线程,但它们的堆栈跟踪只反映了它们的内部状态,并且(显然)没有透露有关它们创建位置的信息。同样从对象内部看(使用变量视图),我无法得出任何进一步的提示。

      【讨论】:

      • “不幸的是它没有”——“它”是什么,它没有什么作用?
      • @EoH,我假设您想发表评论但发送了一个答案。请删除您的答案并发表评论。 (我不知道这怎么还没有被否决))))
      【解决方案5】:

      出于本地调试目的,可以尽早将调试器附加到 Java 应用程序。

      在java.lang.Thread#init(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String, long, java.security.AccessControlContext, boolean) 的末尾设置一个非暂停断点,它将评估和记录以下内容:

      "**" + getName() + "**\n" + Arrays.toString(Thread.currentThread().getStackTrace())
      

      这将输出线程名称以及线程是如何创建的(堆栈跟踪),人们可以通过它进行扫描。

      【讨论】:

        猜你喜欢
        • 2014-04-21
        • 2019-05-17
        • 2011-10-09
        • 1970-01-01
        • 2013-09-30
        • 1970-01-01
        • 1970-01-01
        • 2020-01-06
        • 2014-06-25
        相关资源
        最近更新 更多