Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.svm.core;

import com.oracle.svm.core.dcmd.AbstractDcmd;
import com.oracle.svm.core.dcmd.DcmdParseException;

public class DumpRuntimeCompilationDcmd extends AbstractDcmd {

public DumpRuntimeCompilationDcmd() {
this.name = "VM.runtime_compilation";
this.impact = "low";
}

@Override
public String parseAndExecute(String[] arguments) throws DcmdParseException {
if (arguments.length > 1) {
throw new DcmdParseException("Too many arguments specified");
}

DumpRuntimeCompilationSupport.dump();
return "Dump created.";
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -26,14 +27,13 @@

import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platform.WINDOWS;
import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.svm.core.dcmd.DcmdSupport;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.graal.RuntimeCompilation;
import com.oracle.svm.core.heap.VMOperationInfos;
import com.oracle.svm.core.jdk.RuntimeSupport;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.thread.JavaVMOperation;

import jdk.internal.misc.Signal;

Expand All @@ -47,7 +47,11 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {

@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
RuntimeSupport.getRuntimeSupport().addStartupHook(new DumpRuntimeCompilationStartupHook());
if (VMInspectionOptions.hasAttachSupport()) {
ImageSingletons.lookup(DcmdSupport.class).registerDcmd(new DumpRuntimeCompilationDcmd());
} else {
RuntimeSupport.getRuntimeSupport().addStartupHook(new DumpRuntimeCompilationStartupHook());
}
}
}

Expand All @@ -67,20 +71,7 @@ static void install() {

@Override
public void handle(Signal arg0) {
DumpRuntimeCompiledMethodsOperation vmOp = new DumpRuntimeCompiledMethodsOperation();
vmOp.enqueue();
DumpRuntimeCompilationSupport.dump();
}

private static class DumpRuntimeCompiledMethodsOperation extends JavaVMOperation {
DumpRuntimeCompiledMethodsOperation() {
super(VMOperationInfos.get(DumpRuntimeCompiledMethodsOperation.class, "Dump runtime compiled methods", SystemEffect.SAFEPOINT));
}

@Override
protected void operate() {
Log log = Log.log();
SubstrateDiagnostics.dumpRuntimeCompilation(log);
log.flush();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.oracle.svm.core;

import com.oracle.svm.core.heap.VMOperationInfos;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.thread.JavaVMOperation;

public class DumpRuntimeCompilationSupport {

public static void dump() {
DumpRuntimeCompiledMethodsOperation vmOp = new DumpRuntimeCompiledMethodsOperation();
vmOp.enqueue();
}

private static class DumpRuntimeCompiledMethodsOperation extends JavaVMOperation {
DumpRuntimeCompiledMethodsOperation() {
super(VMOperationInfos.get(DumpRuntimeCompiledMethodsOperation.class, "Dump runtime compiled methods", SystemEffect.SAFEPOINT));
}

@Override
protected void operate() {
Log log = Log.log();
SubstrateDiagnostics.dumpRuntimeCompilation(log);
log.flush();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -24,22 +25,15 @@
*/
package com.oracle.svm.core;

import org.graalvm.nativeimage.CurrentIsolate;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platform.WINDOWS;
import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.svm.core.dcmd.DcmdSupport;
import com.oracle.svm.core.thread.ThreadDumpStacksDcmd;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.heap.VMOperationInfos;
import com.oracle.svm.core.jdk.RuntimeSupport;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.stack.JavaStackWalker;
import com.oracle.svm.core.stack.ThreadStackPrinter.StackFramePrintVisitor;
import com.oracle.svm.core.thread.JavaThreads;
import com.oracle.svm.core.thread.JavaVMOperation;
import com.oracle.svm.core.thread.PlatformThreads;
import com.oracle.svm.core.thread.VMThreads;

import jdk.internal.misc.Signal;

Expand All @@ -53,7 +47,11 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {

@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
RuntimeSupport.getRuntimeSupport().addStartupHook(new DumpThreadStacksOnSignalStartupHook());
if (Platform.includedIn(WINDOWS.class) || !VMInspectionOptions.hasAttachSupport()) {
RuntimeSupport.getRuntimeSupport().addStartupHook(new DumpThreadStacksOnSignalStartupHook());
} else {
ImageSingletons.lookup(DcmdSupport.class).registerDcmd(new ThreadDumpStacksDcmd());
}
}
}

Expand All @@ -73,55 +71,6 @@ static void install() {

@Override
public void handle(Signal arg0) {
DumpAllStacksOperation vmOp = new DumpAllStacksOperation();
vmOp.enqueue();
}

private static class DumpAllStacksOperation extends JavaVMOperation {
DumpAllStacksOperation() {
super(VMOperationInfos.get(DumpAllStacksOperation.class, "Dump all stacks", SystemEffect.SAFEPOINT));
}

@Override
protected void operate() {
Log log = Log.log();
log.string("Full thread dump:").newline().newline();
for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) {
if (vmThread == CurrentIsolate.getCurrentThread()) {
/* Skip the signal handler stack */
continue;
}
try {
dumpStack(log, vmThread);
} catch (Exception e) {
log.string("Exception during dumpStack: ").string(e.getClass().getName()).newline();
log.string(e.getMessage()).newline();
}
}
log.flush();
}

private static void dumpStack(Log log, IsolateThread vmThread) {
Thread javaThread = PlatformThreads.fromVMThread(vmThread);
if (javaThread != null) {
log.character('"').string(javaThread.getName()).character('"');
log.string(" #").signed(JavaThreads.getThreadId(javaThread));
if (javaThread.isDaemon()) {
log.string(" daemon");
}
} else {
log.string("(no Java thread)");
}
log.string(" thread=").zhex(vmThread);
if (javaThread != null) {
log.string(" state=").string(javaThread.getState().name());
}
log.newline();

log.indent(true);
StackFramePrintVisitor visitor = new StackFramePrintVisitor();
JavaStackWalker.walkThread(vmThread, visitor, log);
log.indent(false);
}
DumpThreadStacksSupport.dump();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2024, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.oracle.svm.core;

import org.graalvm.nativeimage.CurrentIsolate;
import org.graalvm.nativeimage.IsolateThread;

import com.oracle.svm.core.heap.VMOperationInfos;
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.stack.JavaStackWalker;
import com.oracle.svm.core.stack.ThreadStackPrinter.StackFramePrintVisitor;
import com.oracle.svm.core.thread.JavaThreads;
import com.oracle.svm.core.thread.JavaVMOperation;
import com.oracle.svm.core.thread.PlatformThreads;
import com.oracle.svm.core.thread.VMThreads;

public class DumpThreadStacksSupport {
public static void dump() {
DumpAllStacksOperation vmOp = new DumpAllStacksOperation();
vmOp.enqueue();
}

private static class DumpAllStacksOperation extends JavaVMOperation {
DumpAllStacksOperation() {
super(VMOperationInfos.get(DumpAllStacksOperation.class, "Dump all stacks", SystemEffect.SAFEPOINT));
}

@Override
protected void operate() {
Log log = Log.log();
log.string("Full thread dump:").newline().newline();
for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) {
if (vmThread == CurrentIsolate.getCurrentThread()) {
/* Skip the signal handler stack */
continue;
}
try {
dumpStack(log, vmThread);
} catch (Exception e) {
log.string("Exception during dumpStack: ").string(e.getClass().getName()).newline();
log.string(e.getMessage()).newline();
}
}
log.flush();
}

private static void dumpStack(Log log, IsolateThread vmThread) {
Thread javaThread = PlatformThreads.fromVMThread(vmThread);
if (javaThread != null) {
log.character('"').string(javaThread.getName()).character('"');
log.string(" #").signed(JavaThreads.getThreadId(javaThread));
if (javaThread.isDaemon()) {
log.string(" daemon");
}
} else {
log.string("(no Java thread)");
}
log.string(" thread=").zhex(vmThread);
if (javaThread != null) {
log.string(" state=").string(javaThread.getState().name());
}
log.newline();

log.indent(true);
StackFramePrintVisitor visitor = new StackFramePrintVisitor();
JavaStackWalker.walkThread(vmThread, visitor, log);
log.indent(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ public final class VMInspectionOptions {
private static final String MONITORING_JMXSERVER_NAME = "jmxserver";
private static final String MONITORING_THREADDUMP_NAME = "threaddump";
private static final String MONITORING_NMT_NAME = "nmt";
private static final String MONITORING_ATTACH_NAME = "attach";

private static final List<String> MONITORING_ALL_VALUES = List.of(MONITORING_HEAPDUMP_NAME, MONITORING_JFR_NAME, MONITORING_JVMSTAT_NAME, MONITORING_JMXCLIENT_NAME, MONITORING_JMXSERVER_NAME,
MONITORING_THREADDUMP_NAME, MONITORING_NMT_NAME, MONITORING_ALL_NAME, MONITORING_DEFAULT_NAME);
MONITORING_THREADDUMP_NAME, MONITORING_NMT_NAME, MONITORING_ATTACH_NAME, MONITORING_ALL_NAME, MONITORING_DEFAULT_NAME);
private static final String MONITORING_ALLOWED_VALUES_TEXT = "'" + MONITORING_HEAPDUMP_NAME + "', '" + MONITORING_JFR_NAME + "', '" + MONITORING_JVMSTAT_NAME + "', '" + MONITORING_JMXSERVER_NAME +
"' (experimental), '" + MONITORING_JMXCLIENT_NAME + "' (experimental), '" + MONITORING_THREADDUMP_NAME + "', '" + MONITORING_NMT_NAME + "' (experimental), or '" +
"' (experimental), '" + MONITORING_JMXCLIENT_NAME + "' (experimental), '" + MONITORING_THREADDUMP_NAME + "', '" + MONITORING_NMT_NAME + "', '" + MONITORING_ATTACH_NAME +
"' (experimental), or '" +
MONITORING_ALL_NAME + "' (deprecated behavior: defaults to '" + MONITORING_ALL_NAME + "' if no argument is provided)";

static {
Expand Down Expand Up @@ -178,6 +180,11 @@ public static boolean hasNativeMemoryTrackingSupport() {
return hasAllOrKeywordMonitoringSupport(MONITORING_NMT_NAME);
}

@Fold
public static boolean hasAttachSupport() {
return hasAllOrKeywordMonitoringSupport(MONITORING_ATTACH_NAME) && !Platform.includedIn(WINDOWS.class);
}

static class DeprecatedOptions {
@Option(help = "Enables features that allow the VM to be inspected during run time.", type = OptionType.User, //
deprecated = true, deprecationMessage = "Please use '--" + ENABLE_MONITORING_OPTION + "'") //
Expand Down
Loading