从特定线程请求堆栈跟踪是否需要所有线程都处于安全点?

Does requesting a stack trace from a particular thread require all threads to be at a safe point?

当通过 Thread#getStackTrace()ThreadMXBean#getThreadInfo(long[], int) 从另一个线程请求堆栈跟踪时,是否所有线程都必须进入安全点并因此必须等待所有其他线程都进入安全点?

This blog 似乎暗示是这样的:

You hit a global safepoint whether you are sampling a single thread or all threads (at least on OpenJDK, Zing is slightly different but as a profiler vendor OpenJDK is your assumption.)

这意味着从单个线程获取堆栈跟踪与获取所有堆栈跟踪一样具有侵入性(就由于全局安全点命中频率增加而导致的高开销而言)。

但是 actually/still 这对 OpenJDK 来说是正确的吗?您有任何关于为什么会这样或相关源代码的指示吗?

在 OpenJDK(到当前 JDK 13)Thread.getStackTrace() 仍然 运行 处于全局停止世界安全点:

Thread.java

public StackTraceElement[] getStackTrace() {
    if (this != Thread.currentThread()) {
        ....
        StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});

这归结为 ThreadService::dump_stack_traces, which executes VM_ThreadDump VM 线程中的操作。所有 VM_* 操作用于 运行 在全局安全点。

JEP 312: Thread-Local Handshakes introduced in JDK 10, provides a per-thread safepoint mechanism. Now VM_Handshake 及其所有后代不需要全局安全点:

class VM_Handshake: public VM_Operation {
  const jlong _handshake_timeout;
 public:
  bool evaluate_at_safepoint() const { return false; }

但是,VM_ThreadDump不是这样的操作。 VM_GetStackTrace 也没有用于实现 JVM TI GetStackTrace 函数。

有一个未解决的问题 JDK-8201641 可以在将来某个时间利用线程本地握手来获取单个线程的堆栈跟踪。