没有堆栈的 Java "Thread-2"会阻止终止

标签 java eclipse multithreading debugging stack-trace

我有一个非常复杂的 Java 程序,它不会终止。 Eclipse 调试器显示一个可以暂停的线程,但没有堆栈跟踪。 它被称为“Thread-2”。

此线程的 jstack -l 输出是:

"Thread-2" #17 prio=5 os_prio=0 tid=0x00007f1268002800 nid=0x3342 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
    - None

我在 Thread.start() 中添加了断点,但找不到名为“Thread-2”的线程。 该线程仅在创建两个“AWT-Event-Queue”线程之后出现。 我不在我的程序中手动创建任何线程。

在主线程和所有其他线程退出,并释放 JFrame 后,以下线程仍然存在:

Thread [AWT-EventQueue-0] (Running) 
Thread [Thread-2] (Running) 
Thread [DestroyJavaVM] (Running)    

挂起VM时,存在以下线程:

Daemon System Thread [Signal Dispatcher] (Suspended)    
Daemon System Thread [Finalizer] (Suspended)    
Daemon System Thread [Reference Handler] (Suspended)    
Daemon System Thread [Java2D Disposer] (Suspended)  
Daemon System Thread [AWT-XAWT] (Suspended) 
Thread [AWT-EventQueue-0] (Suspended)   
Thread [Thread-2] (Suspended)   
Thread [DestroyJavaVM] (Suspended)  

我怎样才能得到关于这个线程的更多信息,或者让它终止?

编辑 1:

根据eclipse pom.xml View 的Dependency Hierarchy,我使用了以下第三方库:

guava 17.0 [compile]
hamcrest-core 1.3 [test]
junit 4.11 [test]
log4j-api 2.0-beta9 [compile]
log4j-core 2.0-beta9 [compile]

编辑 2:

按照https://stackoverflow.com/a/35128213/577485中的建议,为线程类的所有构造函数添加断点,我看到 Thread-0Thread-1 是由 log4j 创建的,但不是 Thread-2。它仍然像以前一样出现,并且在构造时没有断点触发。

编辑 3:

现在它变得令人毛骨悚然。在线程上调用时,甚至 stop() 方法也不起作用。我将它添加到 https://stackoverflow.com/a/35128149/577485 中给出的代码中. 至少 System.exit(int) 仍然有效。但正如评论中所说,我不想使用它。

编辑 4:

关于我的系统的信息:

  • 我正在运行最新稳定版的 Ubuntu 15.10 Wily。我启用了 securityupdatesbackports 存储库。
  • 我的 JVM 版本是:

Java 版本“1.7.0_91” OpenJDK 运行时环境 (IcedTea 2.6.3) (7u91-2.6.3-0ubuntu0.15.10.1) OpenJDK 64 位服务器 VM(构建 24.91-b01,混合模式)

编辑 5:

我用直接从java.com下载的Java版本jre-8u71-linux-x64执行程序,但错误依旧。 jstack -l 显示相同的奇怪线程。请注意,该程序仍然是使用较旧的 Java 版本构建的。 编辑:在使用 oracle.com 的 java8u72 编译它之后,我得到了相同的行为。

编辑 6:

我遍历了所有线程字段,这是输出。我无法从这些字段中得到任何提示,线程甚至没有目标。

name: [C@6b67034
priority: 5
threadQ: null
eetop: 140274638530560
single_step: false
daemon: false
stillborn: false
target: null
group: java.lang.ThreadGroup[name=main,maxpri=10]
contextClassLoader: null
inheritedAccessControlContext: java.security.AccessControlContext@0
threadInitNumber: 3
threadLocals: null
inheritableThreadLocals: null
stackSize: 0
nativeParkEventPointer: 0
tid: 17
threadSeqNumber: 20
threadStatus: 5
parkBlocker: null
blocker: null
blockerLock: java.lang.Object@16267862
MIN_PRIORITY: 1
NORM_PRIORITY: 5
MAX_PRIORITY: 10
EMPTY_STACK_TRACE: [Ljava.lang.StackTraceElement;@453da22c
SUBCLASS_IMPLEMENTATION_PERMISSION: ("java.lang.RuntimePermission" "enableContextClassLoaderOverride")
uncaughtExceptionHandler: null
defaultUncaughtExceptionHandler: null
threadLocalRandomSeed: 0
threadLocalRandomProbe: 0
threadLocalRandomSecondarySeed: 0

编辑 7:

Threadname 字段中添加了一个观察点。它只能由我的分析代码访问,而且似乎从未被写入...

编辑 8:

jstack -F -m 为我的程序抛出一个错误:

Attaching to process ID 10973, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.71-b15
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.tools.jstack.JStack.runJStackTool(JStack.java:140)
    at sun.tools.jstack.JStack.main(JStack.java:106)
Caused by: java.lang.RuntimeException: Unable to deduce type of thread from address 0x00007ff68000c000 (expected type JavaThread, CompilerThread, ServiceThread, JvmtiAgentThread, or SurrogateLockerThread)
    at sun.jvm.hotspot.runtime.Threads.createJavaThreadWrapper(Threads.java:169)
    at sun.jvm.hotspot.runtime.Threads.first(Threads.java:153)
    at sun.jvm.hotspot.tools.PStack.initJFrameCache(PStack.java:200)
    at sun.jvm.hotspot.tools.PStack.run(PStack.java:71)
    at sun.jvm.hotspot.tools.PStack.run(PStack.java:58)
    at sun.jvm.hotspot.tools.PStack.run(PStack.java:53)
    at sun.jvm.hotspot.tools.JStack.run(JStack.java:66)
    at sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:260)
    at sun.jvm.hotspot.tools.Tool.start(Tool.java:223)
    at sun.jvm.hotspot.tools.Tool.execute(Tool.java:118)
    at sun.jvm.hotspot.tools.JStack.main(JStack.java:92)
    ... 6 more
Caused by: sun.jvm.hotspot.types.WrongTypeException: No suitable match    for type of address 0x00007ff68000c000
    at sun.jvm.hotspot.runtime.InstanceConstructor.newWrongTypeException(InstanceConstructor.java:62)
    at sun.jvm.hotspot.runtime.VirtualConstructor.instantiateWrapperFor(VirtualConstructor.java:80)
    at sun.jvm.hotspot.runtime.Threads.createJavaThreadWrapper(Threads.java:165)
    ... 16 more

奇怪线程的类名是java.lang.Thread

我不使用任何命令行参数来执行程序。添加 -Dlog4j2.disable.jmx=true 选项为奇怪的线程提供名称 Thread-1

我将 log4j 更新到 2.5,奇怪的线程现在有了名称 Thread-0,当 -Dlog4j2.disable.jmx=true 选项已给出,Thread-1,如果未给出。

编辑 9:

完全删除了 log4j,错误仍然存​​在。该线程现在称为 Thread-0


Here是项目,如果有帮助的话。

最佳答案

我不明白为什么 Thread.start() 上的断点不起作用,但您也可以尝试通过在 Thread 构造函数上设置断点来拦截线程 >>creation<<,或在(内部)Thread.init() 方法上。

线程名为 Thread-2 的事实意味着它是由生成默认线程名称的构造函数之一创建的。这表明它不是由 JVM 或标准 Java 类库创建的。它还缩小了可用于创建它的构造函数的范围。

How can I get more information about this thread ...

除了设置断点,我想不出任何办法。

... or allow it to terminate?

如果您能找到它的创建位置,您应该能够使用 setDaemon(true) 将其标记为守护线程。但是,这需要在线程启动之前完成。

另一种可能性是通过遍历 ThreadGroup 树然后在其上调用 Thread.interrupt() 来找到线程。 (Thread.getAllStackTraces() 是跟踪线程对象的另一种方法。)但是,不能保证线程会“尊重”中断并关闭。

最后,您可以调用 System.exit(...)


更新

我提到线程可能不遵守 interrupt() 并且我对 stop() 不起作用并不感到惊讶。 (它已被弃用,甚至可能不会在某些平台上实现。)

但是,如果您设法实现了实际找到神秘线程的代码,您可以四处挖掘以找到Thread 子类或Runnable 它被实例化。如果您可以打印出完全限定的类名,那么您就会知道它的来源。 (假设您仍然没有成功设置断点,那么您可能需要使用“讨厌的”反射从线程的私有(private) target 字段中提取可运行对象。)

关于没有堆栈的 Java "Thread-2"会阻止终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35088154/

相关文章:

C++ - Boost.Promise、Boost.Unique_Future 和 move 语义

java - 如何将数据从后台线程移动到ui线程

java - 如何在运行时使用java代码执行脚本

java - 使用 MongoDB 在 Java 中计算距离

java - 非法字符: '\u200c' by jsp file

android - Eclipse ADT : Working but "Terminate" button greyed out. ..?

java - 线程中出现异常 "main"java.lang.UnsatisfiedLinkError : no openalprjni in java. library.path

Java CSVReader 跳过行以及如何转换 csv

multithreading - 同一个进程的多个线程可以在多处理器系统中的不同处理器上运行吗?

java - 如何在 Java 中的 Telegram bot 的 textview 上设置超链接?