Почему событие ExecutionSample HotSpot всегда возвращает STATE_RUNNABLE? - PullRequest
3 голосов
/ 10 февраля 2020

Я использую событие ExecutionSample из HotSpot в OpenJDK11.

У него есть поле для состояния потока, но я вижу только одно значение для поля: 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

1 Ответ

4 голосов
/ 11 февраля 2020

Почему событие 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_native соответствуют STATE_RUNNABLE в формате JFR.

Когда поток не является работоспособный по любой причине (STATE_SLEEPING, STATE_PARKED et c.), его состояние JVM равно thread_blocked. Однако профилировщик метода JFR вообще не производит выборку заблокированных потоков.


Если вас интересует профилирование настенных часов (т. Е. Выборка всех потоков , независимо от того, работают они на ЦП или в спящем режиме) Вы можете посмотреть asyn c -профиль . Asyn c -profiler также может выводить данные в формате, совместимом с JFR, но в отличие от JFR генерирует события ExecutionSample как для потоков RUNNABLE, так и для потоков IDLE.

...