diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat index 4c6b48e5544..51e1ce824c8 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2022 IBM Corp. and others + * Copyright (c) 2021, 2023 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -621,12 +621,15 @@ MM_AllocationContextTarok._allocationContextType = required MM_CardTable._cardTableStart = required MM_CardTable._cardTableVirtualStart = required MM_CardTable._heapBase = required +MM_ContinuationObjectList._head = J9Object* +MM_ContinuationObjectList._nextList = MM_ContinuationObjectList* MM_CopyScanCache.cacheAlloc = required MM_CopyScanCache.cacheTop = required MM_EnvironmentStandard._survivorCopyScanCache = required MM_EnvironmentStandard._tenureCopyScanCache = required MM_GCExtensions.accessBarrier = required MM_GCExtensions.collectStringConstants = required +MM_GCExtensions.continuationObjectLists = MM_ContinuationObjectList* MM_GCExtensions.dynamicClassUnloading = required MM_GCExtensions.finalizeListManager = required MM_GCExtensions.ownableSynchronizerObjectLists = required @@ -709,6 +712,7 @@ MM_MemorySpace._name = required MM_MemorySubSpace._memorySpace = required MM_MemorySubSpace._memoryType = required MM_MemorySubSpaceGeneric._memoryPool = required +MM_ObjectAccessBarrier._continuationLinkOffset = UDATA MM_ObjectAccessBarrier._ownableSynchronizerLinkOffset = required MM_ObjectAccessBarrier._referenceLinkOffset = required MM_OwnableSynchronizerObjectList._head = required diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/pointer/helper/J9ObjectHelper.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/pointer/helper/J9ObjectHelper.java index 334c276b3b9..4826697cf37 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/pointer/helper/J9ObjectHelper.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/pointer/helper/J9ObjectHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2021 IBM Corp. and others + * Copyright (c) 2001, 2023 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -404,7 +404,7 @@ public static J9ObjectPointer getObjectField(J9ObjectPointer objPointer, J9Objec } } - private static J9ObjectFieldOffset getFieldOffset(J9ObjectPointer objPointer, String name, String signature) throws CorruptDataException + public static J9ObjectFieldOffset getFieldOffset(J9ObjectPointer objPointer, String name, String signature) throws CorruptDataException { J9ObjectFieldOffset result = J9ClassHelper.checkFieldOffsetCache(J9ObjectHelper.clazz(objPointer), name, signature); if (result == null) { diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java index dd963fc3a2f..8d7a967360b 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2022 IBM Corp. and others + * Copyright (c) 2010, 2023 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -204,6 +204,7 @@ public void run(IVMData vmData, Object[] userData) if (ValueTypeHelper.getValueTypeHelper().areValueTypesSupported()) { toPassBack.add(new FlatObjectCommand()); } + toPassBack.add(new VirtualThreadsCommand()); loadPlugins(toPassBack, loader); diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/JavaVersionHelper.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/JavaVersionHelper.java index a01ebfad622..2d37ec5ef28 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/JavaVersionHelper.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/JavaVersionHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2018 IBM Corp. and others + * Copyright (c) 2018, 2023 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -25,30 +25,43 @@ import com.ibm.j9ddr.CorruptDataException; import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer; -import com.ibm.j9ddr.vm29.types.UDATA; /** * JavaVersionHelper helps check if the JVM version is new enough for the modularity DDR commands */ public class JavaVersionHelper { - public final static int J2SE_SERVICE_RELEASE_MASK = 0xFFFF; - public final static int J2SE_19 = 9; - public final static int J2SE_JAVA_SPEC_VERSION_SHIFT = 8; + private final static int J2SE_SERVICE_RELEASE_MASK = 0xFFFF; + private final static int J2SE_JAVA_SPEC_VERSION_SHIFT = 8; /** - * Returns true if the Java version is Java9 and up. + * Returns {@code true} if the Java version is Java9 or higher. * @param vm J9JavaVMPointer - * @param out The output print stream - * @return if the Java version is Java9 and up or not. + * @param out the output print stream + * @return {@code true} if the Java version is Java9 or higher * @throws CorruptDataException + * @deprecated use {@link #ensureMinimumJavaVersion(int, J9JavaVMPointer, PrintStream)} instead */ - public static boolean ensureJava9AndUp(J9JavaVMPointer vm, PrintStream out) throws CorruptDataException + @Deprecated + public static boolean ensureJava9AndUp(J9JavaVMPointer vm, PrintStream out) throws CorruptDataException { - int javaVersion = vm.j2seVersion().bitAnd(J2SE_SERVICE_RELEASE_MASK).intValue() >> J2SE_JAVA_SPEC_VERSION_SHIFT; - if (javaVersion < J2SE_19) { - out.printf("This command only works with core file created by VM with Java version 9 or higher%n" - + "The current VM Java version is: %s%n", javaVersion); + return ensureMinimumJavaVersion(9, vm, out); + } + + /** + * Returns {@code true} if the Java version is {@code version} or higher. + * @param version the minimum version + * @param vm J9JavaVMPointer + * @param out the output print stream + * @return {@code true} if the Java version is {@code version} or higher + * @throws CorruptDataException + */ + public static boolean ensureMinimumJavaVersion(int version, J9JavaVMPointer vm, PrintStream out) throws CorruptDataException + { + int javaVersion = vm.j2seVersion().bitAnd(J2SE_SERVICE_RELEASE_MASK).rightShift(J2SE_JAVA_SPEC_VERSION_SHIFT).intValue(); + if (javaVersion < version) { + out.printf("This command only works with core file created by VM with Java version %d or higher.%n" + + "The current VM Java version is: %s.%n", version, javaVersion); return false; } return true; diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/VirtualThreadsCommand.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/VirtualThreadsCommand.java new file mode 100644 index 00000000000..36a23130f0c --- /dev/null +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/VirtualThreadsCommand.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2022, 2023 IBM Corp. and others + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] https://openjdk.org/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception + *******************************************************************************/ +package com.ibm.j9ddr.vm29.tools.ddrinteractive; + +import java.io.PrintStream; + +import com.ibm.j9ddr.CorruptDataException; +import com.ibm.j9ddr.tools.ddrinteractive.Command; +import com.ibm.j9ddr.tools.ddrinteractive.Context; +import com.ibm.j9ddr.tools.ddrinteractive.DDRInteractiveCommandException; +import com.ibm.j9ddr.vm29.j9.DataType; +import com.ibm.j9ddr.vm29.j9.J9ObjectFieldOffset; +import com.ibm.j9ddr.vm29.j9.gc.GCBase; +import com.ibm.j9ddr.vm29.pointer.ObjectReferencePointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9ObjectPointer; +import com.ibm.j9ddr.vm29.pointer.generated.MM_ContinuationObjectListPointer; +import com.ibm.j9ddr.vm29.pointer.generated.MM_GCExtensionsPointer; +import com.ibm.j9ddr.vm29.pointer.helper.J9ObjectHelper; +import com.ibm.j9ddr.vm29.pointer.helper.J9RASHelper; +import com.ibm.j9ddr.vm29.types.UDATA; + +/** + * vthreads command lists all the virtual threads. + * + * Example: + * !vthreads + * Example output: + * !continuationstack 0x00007fe78c0f9600 !j9vmcontinuation 0x00007fe78c0f9600 !j9object 0x0000000706401588 (Continuation) !j9object 0x0000000706400FB0 (VThread) - name1 + * !continuationstack 0x00007fe78c23aa80 !j9vmcontinuation 0x00007fe78c23aa80 !j9object 0x0000000706424F90 (Continuation) !j9object 0x0000000706424EF0 (VThread) - name2 + * !continuationstack 0x00007fe78c244ac0 !j9vmcontinuation 0x00007fe78c244ac0 !j9object 0x00000007064250D8 (Continuation) !j9object 0x0000000706425038 (VThread) - name3 + * ... + */ +public class VirtualThreadsCommand extends Command { + private static J9ObjectFieldOffset vthreadOffset; + private static J9ObjectFieldOffset vmRefOffset; + private static J9ObjectFieldOffset nameOffset; + + private static J9ObjectPointer getVirtualThread(J9ObjectPointer continuation) throws CorruptDataException { + if (vthreadOffset == null) { + vthreadOffset = J9ObjectHelper.getFieldOffset(continuation, "vthread", "Ljava/lang/Thread;"); + } + return J9ObjectHelper.getObjectField(continuation, vthreadOffset); + } + + private static long getVmRef(J9ObjectPointer continuation) throws CorruptDataException { + if (vmRefOffset == null) { + vmRefOffset = J9ObjectHelper.getFieldOffset(continuation, "vmRef", "J"); + } + return J9ObjectHelper.getLongField(continuation, vmRefOffset); + } + + private static J9ObjectPointer getName(J9ObjectPointer vthread) throws CorruptDataException { + if (nameOffset == null) { + nameOffset = J9ObjectHelper.getFieldOffset(vthread, "name", "Ljava/lang/String;"); + } + return J9ObjectHelper.getObjectField(vthread, nameOffset); + } + + public VirtualThreadsCommand() { + addCommand("vthreads", "", "Lists virtual threads"); + } + + @Override + public void run(String command, String[] args, Context context, PrintStream out) throws DDRInteractiveCommandException { + try { + J9JavaVMPointer vm = J9RASHelper.getVM(DataType.getJ9RASPointer()); + if (JavaVersionHelper.ensureMinimumJavaVersion(19, vm, out)) { + displayVirtualThreads(vm, out); + } + } catch (CorruptDataException | NoSuchFieldException e) { + throw new DDRInteractiveCommandException(e); + } + } + + /** + * Prints all the live virtual threads. + * + * @param vm the J9JavaVMPointer of the virtual machine + * @param out the PrintStream to write output to + */ + private static void displayVirtualThreads(J9JavaVMPointer vm, PrintStream out) throws CorruptDataException, NoSuchFieldException { + String addressFormat = "0x%0" + (UDATA.SIZEOF * 2) + "x"; + String outputFormat = "!continuationstack " + addressFormat + + " !j9vmcontinuation " + addressFormat + + " !j9object %s (Continuation) !j9object %s (VThread) - %s%n"; + MM_GCExtensionsPointer extensions = GCBase.getExtensions(); + UDATA linkOffset = extensions.accessBarrier()._continuationLinkOffset(); + MM_ContinuationObjectListPointer continuationObjectList = extensions.continuationObjectLists(); + + while (continuationObjectList.notNull()) { + J9ObjectPointer continuation = continuationObjectList._head(); + while (continuation.notNull()) { + long vmRef = getVmRef(continuation); + J9ObjectPointer vthread = getVirtualThread(continuation); + J9ObjectPointer name = getName(vthread); + + out.format( + outputFormat, + vmRef, + vmRef, + continuation.getHexAddress(), + vthread.getHexAddress(), + J9ObjectHelper.stringValue(name)); + continuation = ObjectReferencePointer.cast(continuation.addOffset(linkOffset)).at(0); + } + continuationObjectList = continuationObjectList._nextList(); + } + } +} diff --git a/runtime/rasdump/trigger.c b/runtime/rasdump/trigger.c index 4c3c04f994b..1e68a8c9e4a 100644 --- a/runtime/rasdump/trigger.c +++ b/runtime/rasdump/trigger.c @@ -681,6 +681,7 @@ prepareForDump(struct J9JavaVM *vm, struct J9RASdumpAgent *agent, struct J9RASdu /* If exclusive access has been obtained, do the requested preparation */ if (newState & J9RAS_DUMP_GOT_EXCLUSIVE_VM_ACCESS) { vm->memoryManagerFunctions->j9gc_flush_caches_for_walk(vm); + vm->memoryManagerFunctions->j9gc_flush_nonAllocationCaches_for_walk(vm); newState |= J9RAS_DUMP_HEAP_PREPARED; } }