8339307: jhsdb jstack could not trace FFM upcall frame
Reviewed-by: cjplummer, jvernee
This commit is contained in:
parent
fbe2629303
commit
deeb09a640
@ -595,6 +595,7 @@ class UpcallLinker;
|
||||
|
||||
// A (Panama) upcall stub. Not used by JNI.
|
||||
class UpcallStub: public RuntimeBlob {
|
||||
friend class VMStructs;
|
||||
friend class UpcallLinker;
|
||||
private:
|
||||
jobject _receiver;
|
||||
|
@ -563,6 +563,12 @@
|
||||
\
|
||||
nonstatic_field(DeoptimizationBlob, _unpack_offset, int) \
|
||||
\
|
||||
/*****************************************************/ \
|
||||
/* UpcallStubs (NOTE: incomplete, but only a little) */ \
|
||||
/*****************************************************/ \
|
||||
\
|
||||
nonstatic_field(UpcallStub, _frame_data_offset, ByteSize) \
|
||||
\
|
||||
/**************************************************/ \
|
||||
/* NMethods (NOTE: incomplete, but only a little) */ \
|
||||
/**************************************************/ \
|
||||
@ -1012,7 +1018,9 @@
|
||||
nonstatic_field(AccessFlags, _flags, jint) \
|
||||
nonstatic_field(elapsedTimer, _counter, jlong) \
|
||||
nonstatic_field(elapsedTimer, _active, bool) \
|
||||
nonstatic_field(InvocationCounter, _counter, unsigned int)
|
||||
nonstatic_field(InvocationCounter, _counter, unsigned int) \
|
||||
\
|
||||
nonstatic_field(UpcallStub::FrameData, jfa, JavaFrameAnchor)
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// VM_TYPES
|
||||
@ -1306,6 +1314,7 @@
|
||||
declare_type(nmethod, CodeBlob) \
|
||||
declare_type(RuntimeStub, RuntimeBlob) \
|
||||
declare_type(SingletonBlob, RuntimeBlob) \
|
||||
declare_type(UpcallStub, RuntimeBlob) \
|
||||
declare_type(SafepointBlob, SingletonBlob) \
|
||||
declare_type(DeoptimizationBlob, SingletonBlob) \
|
||||
declare_c2_type(ExceptionBlob, SingletonBlob) \
|
||||
@ -1900,6 +1909,7 @@
|
||||
declare_integer_type(BasicType) /* FIXME: wrong type (not integer) */ \
|
||||
\
|
||||
declare_integer_type(CompLevel) \
|
||||
declare_integer_type(ByteSize) \
|
||||
JVMTI_ONLY(declare_toplevel_type(BreakpointInfo)) \
|
||||
JVMTI_ONLY(declare_toplevel_type(BreakpointInfo*)) \
|
||||
declare_toplevel_type(CodeBlob*) \
|
||||
@ -1948,6 +1958,7 @@
|
||||
declare_type(FileMapInfo, CHeapObj<mtInternal>) \
|
||||
declare_toplevel_type(FileMapHeader) \
|
||||
declare_toplevel_type(CDSFileMapRegion) \
|
||||
declare_toplevel_type(UpcallStub::FrameData) \
|
||||
\
|
||||
/************/ \
|
||||
/* GC types */ \
|
||||
|
@ -143,6 +143,8 @@ public class CodeBlob extends VMObject {
|
||||
|
||||
public boolean isRuntimeStub() { return false; }
|
||||
|
||||
public boolean isUpcallStub() { return false; }
|
||||
|
||||
public boolean isDeoptimizationStub() { return false; }
|
||||
|
||||
public boolean isUncommonTrapStub() { return false; }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. 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
|
||||
@ -60,6 +60,7 @@ public class CodeCache {
|
||||
virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class);
|
||||
virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class);
|
||||
virtualConstructor.addMapping("VtableBlob", VtableBlob.class);
|
||||
virtualConstructor.addMapping("UpcallStub", UpcallStub.class);
|
||||
virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class);
|
||||
virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class);
|
||||
if (VM.getVM().isServerCompiler()) {
|
||||
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
* 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 sun.jvm.hotspot.code;
|
||||
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.Observable;
|
||||
import sun.jvm.hotspot.utilities.Observer;
|
||||
|
||||
public class UpcallStub extends RuntimeBlob {
|
||||
|
||||
private static CIntegerField frameDataOffsetField;
|
||||
private static AddressField lastJavaFPField;
|
||||
private static AddressField lastJavaSPField;
|
||||
private static AddressField lastJavaPCField;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("UpcallStub");
|
||||
frameDataOffsetField = type.getCIntegerField("_frame_data_offset");
|
||||
|
||||
Type anchorType = db.lookupType("JavaFrameAnchor");
|
||||
lastJavaSPField = anchorType.getAddressField("_last_Java_sp");
|
||||
lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
|
||||
|
||||
try {
|
||||
lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
|
||||
} catch (Exception e) {
|
||||
// Some platforms (e.g. PPC64) does not have this field.
|
||||
lastJavaFPField = null;
|
||||
}
|
||||
}
|
||||
|
||||
public UpcallStub(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
protected Address getJavaFrameAnchor(Frame frame) {
|
||||
var frameDataOffset = frameDataOffsetField.getValue(addr);
|
||||
var frameDataAddr = frame.getUnextendedSP().addOffsetTo(frameDataOffset);
|
||||
var frameData = VMObjectFactory.newObject(FrameData.class, frameDataAddr);
|
||||
return frameData.getJavaFrameAnchor();
|
||||
}
|
||||
|
||||
public Address getLastJavaSP(Frame frame) {
|
||||
return lastJavaSPField.getValue(getJavaFrameAnchor(frame));
|
||||
}
|
||||
|
||||
public Address getLastJavaFP(Frame frame) {
|
||||
return lastJavaFPField == null ? null : lastJavaFPField.getValue(getJavaFrameAnchor(frame));
|
||||
}
|
||||
|
||||
public Address getLastJavaPC(Frame frame) {
|
||||
return lastJavaPCField.getValue(getJavaFrameAnchor(frame));
|
||||
}
|
||||
|
||||
public boolean isUpcallStub() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class FrameData extends VMObject {
|
||||
|
||||
private static AddressField jfaField;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
initialize(VM.getVM().getTypeDataBase());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("UpcallStub::FrameData");
|
||||
jfaField = type.getAddressField("jfa");
|
||||
}
|
||||
|
||||
public FrameData(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public Address getJavaFrameAnchor() {
|
||||
return addr.addOffsetTo(jfaField.getOffset());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -292,7 +292,7 @@ public class AARCH64Frame extends Frame {
|
||||
}
|
||||
|
||||
if (cb != null) {
|
||||
return senderForCompiledFrame(map, cb);
|
||||
return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
|
||||
}
|
||||
|
||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||
@ -327,6 +327,34 @@ public class AARCH64Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
private Frame senderForUpcallStub(AARCH64RegisterMap map, UpcallStub stub) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForUpcallStub");
|
||||
}
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map != null, "map must be set");
|
||||
}
|
||||
|
||||
var lastJavaFP = stub.getLastJavaFP(this);
|
||||
var lastJavaSP = stub.getLastJavaSP(this);
|
||||
var lastJavaPC = stub.getLastJavaPC(this);
|
||||
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(lastJavaSP.greaterThan(getSP()), "must be above this frame on stack");
|
||||
}
|
||||
AARCH64Frame fr;
|
||||
if (lastJavaPC != null) {
|
||||
fr = new AARCH64Frame(lastJavaSP, lastJavaFP, lastJavaPC);
|
||||
} else {
|
||||
fr = new AARCH64Frame(lastJavaSP, lastJavaFP);
|
||||
}
|
||||
map.clear();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. 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
|
||||
@ -279,7 +279,7 @@ public class PPC64Frame extends Frame {
|
||||
}
|
||||
|
||||
if (cb != null) {
|
||||
return senderForCompiledFrame(map, cb);
|
||||
return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
|
||||
}
|
||||
|
||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||
@ -314,6 +314,34 @@ public class PPC64Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
private Frame senderForUpcallStub(PPC64RegisterMap map, UpcallStub stub) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForUpcallStub");
|
||||
}
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map != null, "map must be set");
|
||||
}
|
||||
|
||||
var lastJavaFP = stub.getLastJavaFP(this); // This will be null
|
||||
var lastJavaSP = stub.getLastJavaSP(this);
|
||||
var lastJavaPC = stub.getLastJavaPC(this);
|
||||
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(lastJavaSP.greaterThan(getSP()), "must be above this frame on stack");
|
||||
}
|
||||
PPC64Frame fr;
|
||||
if (lastJavaPC != null) {
|
||||
fr = new PPC64Frame(lastJavaSP, lastJavaFP, lastJavaPC);
|
||||
} else {
|
||||
fr = new PPC64Frame(lastJavaSP, lastJavaFP);
|
||||
}
|
||||
map.clear();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Red Hat Inc.
|
||||
* Copyright (c) 2021, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -284,7 +284,7 @@ public class RISCV64Frame extends Frame {
|
||||
}
|
||||
|
||||
if (cb != null) {
|
||||
return senderForCompiledFrame(map, cb);
|
||||
return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
|
||||
}
|
||||
|
||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||
@ -319,6 +319,34 @@ public class RISCV64Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
private Frame senderForUpcallStub(RISCV64RegisterMap map, UpcallStub stub) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForUpcallStub");
|
||||
}
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map != null, "map must be set");
|
||||
}
|
||||
|
||||
var lastJavaFP = stub.getLastJavaFP(this);
|
||||
var lastJavaSP = stub.getLastJavaSP(this);
|
||||
var lastJavaPC = stub.getLastJavaPC(this);
|
||||
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(lastJavaSP.greaterThan(getSP()), "must be above this frame on stack");
|
||||
}
|
||||
RISCV64Frame fr;
|
||||
if (lastJavaPC != null) {
|
||||
fr = new RISCV64Frame(lastJavaSP, lastJavaFP, lastJavaPC);
|
||||
} else {
|
||||
fr = new RISCV64Frame(lastJavaSP, lastJavaFP);
|
||||
}
|
||||
map.clear();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. 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
|
||||
@ -289,7 +289,7 @@ public class X86Frame extends Frame {
|
||||
}
|
||||
|
||||
if (cb != null) {
|
||||
return senderForCompiledFrame(map, cb);
|
||||
return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb);
|
||||
}
|
||||
|
||||
// Must be native-compiled frame, i.e. the marshaling code for native
|
||||
@ -324,6 +324,34 @@ public class X86Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
private Frame senderForUpcallStub(X86RegisterMap map, UpcallStub stub) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForUpcallStub");
|
||||
}
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map != null, "map must be set");
|
||||
}
|
||||
|
||||
var lastJavaFP = stub.getLastJavaFP(this);
|
||||
var lastJavaSP = stub.getLastJavaSP(this);
|
||||
var lastJavaPC = stub.getLastJavaPC(this);
|
||||
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(lastJavaSP.greaterThan(getSP()), "must be above this frame on stack");
|
||||
}
|
||||
X86Frame fr;
|
||||
if (lastJavaPC != null) {
|
||||
fr = new X86Frame(lastJavaSP, lastJavaFP, lastJavaPC);
|
||||
} else {
|
||||
fr = new X86Frame(lastJavaSP, lastJavaFP);
|
||||
}
|
||||
map.clear();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
|
@ -0,0 +1,75 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
public class LingeredAppWithFFMUpcall extends LingeredApp {
|
||||
|
||||
public static final String THREAD_NAME = "Upcall thread";
|
||||
|
||||
private static final Object lockObj = new Object();
|
||||
|
||||
private static final CountDownLatch signal = new CountDownLatch(1);
|
||||
|
||||
static {
|
||||
System.loadLibrary("upcall");
|
||||
}
|
||||
|
||||
public static void upcall() {
|
||||
signal.countDown();
|
||||
synchronized(lockObj) {
|
||||
}
|
||||
}
|
||||
|
||||
public static long createFunctionPointerForUpcall() throws NoSuchMethodException, IllegalAccessException {
|
||||
var mh = MethodHandles.lookup()
|
||||
.findStatic(LingeredAppWithFFMUpcall.class, "upcall", MethodType.methodType(void.class));
|
||||
var stub = Linker.nativeLinker()
|
||||
.upcallStub(mh, FunctionDescriptor.ofVoid(), Arena.global());
|
||||
return stub.address();
|
||||
}
|
||||
|
||||
public static native void callJNI(long upcallAddr);
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
long upcallAddr = createFunctionPointerForUpcall();
|
||||
var upcallThread = new Thread(() -> callJNI(upcallAddr), THREAD_NAME);
|
||||
synchronized(lockObj) {
|
||||
upcallThread.start();
|
||||
signal.await();
|
||||
LingeredApp.main(args);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
import jdk.test.lib.SA.SATestUtils;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8339307
|
||||
* @requires vm.hasSA
|
||||
* @library /test/lib
|
||||
* @run driver TestJhsdbJstackUpcall
|
||||
*/
|
||||
public class TestJhsdbJstackUpcall {
|
||||
|
||||
private static void runJstack(LingeredApp app) throws Exception {
|
||||
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
|
||||
launcher.addVMArgs(Utils.getTestJavaOpts());
|
||||
launcher.addToolArg("jstack");
|
||||
launcher.addToolArg("--pid");
|
||||
launcher.addToolArg(Long.toString(app.getPid()));
|
||||
|
||||
ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher);
|
||||
Process jhsdb = pb.start();
|
||||
OutputAnalyzer out = new OutputAnalyzer(jhsdb);
|
||||
|
||||
jhsdb.waitFor();
|
||||
|
||||
System.out.println(out.getStdout());
|
||||
System.err.println(out.getStderr());
|
||||
|
||||
out.shouldContain(LingeredAppWithFFMUpcall.THREAD_NAME);
|
||||
out.shouldContain("LingeredAppWithFFMUpcall.upcall()");
|
||||
out.shouldContain("jdk.internal.foreign.abi.UpcallStub");
|
||||
out.shouldContain("LingeredAppWithFFMUpcall.callJNI");
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
|
||||
LingeredApp app = null;
|
||||
|
||||
try {
|
||||
// Needed for LingeredAppWithFFMUpcall to be able to resolve native library.
|
||||
String libPath = System.getProperty("java.library.path");
|
||||
String[] vmArgs = (libPath != null)
|
||||
? Utils.prependTestJavaOpts("-Djava.library.path=" + libPath)
|
||||
: Utils.getTestJavaOpts();
|
||||
|
||||
app = new LingeredAppWithFFMUpcall();
|
||||
LingeredApp.startAppExactJvmOpts(app, vmArgs);
|
||||
System.out.println("Started LingeredAppWithFFMUpcall with pid " + app.getPid());
|
||||
runJstack(app);
|
||||
System.out.println("Test Completed");
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} finally {
|
||||
LingeredApp.stopApp(app);
|
||||
}
|
||||
}
|
||||
}
|
32
test/hotspot/jtreg/serviceability/sa/libupcall.c
Normal file
32
test/hotspot/jtreg/serviceability/sa/libupcall.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
typedef void (*upcall_func)(void);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_LingeredAppWithFFMUpcall_callJNI(JNIEnv *env, jclass cls, jlong upcallAddr) {
|
||||
upcall_func upcall = (upcall_func)upcallAddr;
|
||||
upcall();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user