[debugger] fix reading OpenJ9 fields during Thread Dump, IDEA-374608

OpenJ9 has field "isDaemon" instead of HotSpot's "daemon".


(cherry picked from commit 535f255fb3012369b790f60f9c9f3752291be2fb)

IJ-CR-166058

GitOrigin-RevId: ae6eea0dccf5770b3598b8a3bccc9f7ab5061b72
This commit is contained in:
Vladimir Parfinenko
2025-06-20 14:09:01 +02:00
committed by intellij-monorepo-bot
parent 92a0ba81f5
commit 1ce3a2d250

View File

@@ -224,29 +224,36 @@ private fun threadName(threadReference: ThreadReference): String =
private fun threadName(threadNameRaw: String, threadReference: ObjectReference): String =
threadNameRaw + "@" + threadReference.uniqueID()
private inline fun <reified T : Type> findThreadFieldImpl(fieldName: String, typeToSearch: ReferenceType): Field? {
val field = DebuggerUtils.findField(typeToSearch, fieldName)
if (field == null) {
return null
}
if (field.type() !is T) {
private inline fun <reified T : Type> findThreadFieldImpl(fieldNames: List<String>, typeToSearch: ReferenceType): Field? {
val wellNamedFields = fieldNames.mapNotNull { DebuggerUtils.findField(typeToSearch, it) }
if (wellNamedFields.isEmpty()) return null
val wellTypedFields = wellNamedFields.filter { it.type() is T }
if (wellTypedFields.isEmpty()) {
val vm = typeToSearch.virtualMachine()
logger<ThreadDumpAction>().error(
"$typeToSearch has field '$fieldName' with an unexpected type ${field.type()}, skipping it. " +
"$typeToSearch has following fields ${wellNamedFields.map { it.name() }} with unexpected types ${wellNamedFields.map { it.type() }}, skipping it. " +
"VM: ${vm.name()}, ${vm.version()}.")
return null
}
return field
if (wellTypedFields.size > 1) {
val vm = typeToSearch.virtualMachine()
logger<ThreadDumpAction>().error(
"$typeToSearch has ambiguous list of fields ${wellTypedFields.map { it.name() }}, taking the first one. " +
"VM: ${vm.name()}, ${vm.version()}.")
}
return wellTypedFields.first()
}
private inline fun <reified T : Type> findThreadField(fieldName: String, jlThreadType: ReferenceType, fieldHolderType: ReferenceType?, optional: Boolean = false): Field? {
findThreadFieldImpl<T>(fieldName, jlThreadType)?.let {
private inline fun <reified T : Type> findThreadField(fieldNames: List<String>, jlThreadType: ReferenceType, fieldHolderType: ReferenceType?, optional: Boolean = false): Field? {
findThreadFieldImpl<T>(fieldNames, jlThreadType)?.let {
return it
}
if (fieldHolderType != null) {
findThreadFieldImpl<T>(fieldName, fieldHolderType)?.let {
findThreadFieldImpl<T>(fieldNames, fieldHolderType)?.let {
return it
}
}
@@ -259,13 +266,16 @@ private inline fun <reified T : Type> findThreadField(fieldName: String, jlThrea
} else {
"$jlThreadType has "
} +
"no field '$fieldName'. " +
"none of fields $fieldNames. " +
"VM: ${vm.name()}, ${vm.version()}.")
}
return null
}
private inline fun <reified T : Type> findThreadField(fieldName: String, jlThreadType: ReferenceType, fieldHolderType: ReferenceType?, optional: Boolean = false): Field? =
findThreadField<T>(listOf(fieldName), jlThreadType, fieldHolderType, optional)
private fun buildThreadStates(
vmProxy: VirtualMachineProxyImpl,
platformThreads: List<ThreadReference>,
@@ -284,7 +294,7 @@ private fun buildThreadStates(
val holderField = findThreadField<ClassType>("holder", jlThreadType, null, optional = true)
val fieldHolderType = holderField?.type()?.let { it as ClassType }
val daemonField = findThreadField<BooleanType>("daemon", jlThreadType, fieldHolderType)
val daemonField = findThreadField<BooleanType>(listOf("daemon", "isDaemon"), jlThreadType, fieldHolderType)
val priorityField = findThreadField<IntegerType>("priority", jlThreadType, fieldHolderType)
val tidField = findThreadField<LongType>("tid", jlThreadType, fieldHolderType)