3

我在 OpenJDK11 中使用 HotSpot 的ExecutionSample 事件

它有一个线程状态字段,但我只看到该字段的一个值:STATE_RUNNABLE

HotSpot 如何选择要采样的线程?为什么它们总是可运行的?

Kotlin 中的简单复制代码:

import jdk.jfr.Recording
import jdk.jfr.consumer.RecordingFile
import java.nio.file.Path

object ExecutionSampleTest {

    private const val EXECUTION_SAMPLE = "jdk.ExecutionSample"
    private val RECORDING_PATH = Path.of("/tmp/recording.jfr")

    @JvmStatic
    fun main(args: Array<String>) {
        Recording().use { recording ->
            recording.enable(EXECUTION_SAMPLE)
            recording.settings = recording.settings.plus("$EXECUTION_SAMPLE#period" to "1 ms")

            recording.start()
            repeat(100) {
                // start some sleeping threads, just so we've got something to sample
                Thread { Thread.sleep(20_000) }.start()
            }
            Thread.sleep(20_000)
            recording.stop()
            recording.dump(RECORDING_PATH)

            RecordingFile.readAllEvents(RECORDING_PATH).forEach {
                println("Thread state: ${it.getString("state")}")
            }
        }
    }
}

只打印:Thread state: STATE_RUNNABLE

4

1 回答 1

5

为什么 HotSpot ExecutionSample 事件总是返回 STATE_RUNNABLE?

按设计。

JFR 方法分析器定期对 Java 线程进行采样并产生两种类型的事件:

  • ExecutionSample, 当线程状态为in_java
  • NativeMethodSample, 当线程状态为in_native

参见jfrThreadSampler.cpp源代码:

  if (JAVA_SAMPLE == type) {
    if (thread_state_in_java(thread)) {
      ret = sample_thread_in_java(thread, frames, max_frames);
    }
  } else {
    assert(NATIVE_SAMPLE == type, "invariant");
    if (thread_state_in_native(thread)) {
      ret = sample_thread_in_native(thread, frames, max_frames);
    }
  }

两者都in_java对应in_nativeSTATE_RUNNABLEJFR 格式。

当线程由于任一原因(等)而无法运行时STATE_SLEEPINGSTATE_PARKED其 JVM 状态为thread_blocked. 但是,JFR 方法分析器根本不会对阻塞的线程进行采样。


如果您对挂钟分析感兴趣(即对所有线程进行采样,无论它们是在 CPU 上运行还是在睡眠中运行),您可能需要查看async-profiler。Async-profiler 还可以生成 JFR 兼容格式的输出,但与 JFR 不同的是,它ExecutionSample为 RUNNABLE 和 IDLE 线程生成事件。

于 2020-02-11T01:00:11.813 回答