78cb6776b6
Reviewed-by: sspitsyn
189 lines
7.4 KiB
Java
189 lines
7.4 KiB
Java
/*
|
|
* Copyright (c) 2018, 2021, 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.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
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
|
|
* @key randomness
|
|
* @bug 8208091
|
|
* @requires (os.family == "linux") & (vm.hasSA)
|
|
* @library /test/lib
|
|
* @run driver TestJhsdbJstackMixed
|
|
*/
|
|
public class TestJhsdbJstackMixed {
|
|
|
|
private static final int MAX_ITERATIONS = 20;
|
|
private static final String NATIVE_FUNCTION_NAME = "fib";
|
|
private static final String LINE_MATCHER_STR = ".*" + NATIVE_FUNCTION_NAME
|
|
+ ".*";
|
|
private static final Pattern LINE_PATTERN = Pattern
|
|
.compile(LINE_MATCHER_STR);
|
|
private static final String HEX_STR_PATTERN = "0x([a-fA-F0-9]+)";
|
|
private static final String FIB_SPLIT_PATTERN = NATIVE_FUNCTION_NAME
|
|
+ "\\s+\\+";
|
|
private static final Pattern HEX_PATTERN = Pattern.compile(HEX_STR_PATTERN);
|
|
private static final int ADDRESS_ALIGNMENT_X86 = 4;
|
|
|
|
/*
|
|
* UnmappedAddressException will be thrown iff:
|
|
* - The JNI code is being compiled with -fomit-frame-pointer AND
|
|
* - The JNI code is currently executing at address A = pc() + offset
|
|
* where A % ADDRESS_SIZE == 0.
|
|
*
|
|
* In the below example we have: pc() == f6401546, offset == 56,
|
|
* ADDRESS_SIZE == 4. Thus, A == F640159C which satisfies this condition.
|
|
*
|
|
* "NoFramePointerJNIFib" #11 prio=5 tid=0xa357bc00 nid=0x6de9 runnable [0xa365b000]
|
|
* java.lang.Thread.State: RUNNABLE
|
|
* JavaThread state: _thread_in_native
|
|
* 0xf6401546 fib + 0x56
|
|
*/
|
|
private static boolean isFibAndAlignedAddress(List<String> lines) {
|
|
List<String> fibLines = findFibLines(lines);
|
|
System.out.println("DEBUG: " + fibLines);
|
|
// we're only interested in the first matched line.
|
|
if (fibLines.size() >= 1) {
|
|
String line = fibLines.get(0);
|
|
return isMatchLine(line);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static boolean isMatchLine(String line) {
|
|
String[] tokens = line.split(FIB_SPLIT_PATTERN);
|
|
if (tokens.length != 2) {
|
|
return false; // NOT exactly two tokens, ignore.
|
|
}
|
|
String pcRaw = tokens[0].trim();
|
|
String offsetRaw = tokens[1].trim();
|
|
Matcher matcher = HEX_PATTERN.matcher(pcRaw);
|
|
long pcVal = 3;
|
|
boolean pcMatched = matcher.matches();
|
|
if (pcMatched) {
|
|
String pc = matcher.group(1);
|
|
pcVal = Long.parseUnsignedLong(pc, 16);
|
|
}
|
|
matcher = HEX_PATTERN.matcher(offsetRaw);
|
|
long offsetVal = 0;
|
|
boolean offsetMatched = matcher.matches();
|
|
if (offsetMatched) {
|
|
String offset = matcher.group(1);
|
|
offsetVal = Long.parseUnsignedLong(offset, 16);
|
|
}
|
|
if (offsetMatched && pcMatched
|
|
&& (pcVal + offsetVal) % ADDRESS_ALIGNMENT_X86 == 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static List<String> findFibLines(List<String> lines) {
|
|
boolean startReached = false;
|
|
boolean endReached = false;
|
|
List<String> interestingLines = new ArrayList<>();
|
|
for (String line : lines) {
|
|
if (line.contains(LingeredAppWithNativeMethod.THREAD_NAME)) {
|
|
startReached = true;
|
|
}
|
|
if (startReached && line.contains("-------")) {
|
|
endReached = true;
|
|
}
|
|
if (startReached && !endReached) {
|
|
Matcher matcher = LINE_PATTERN.matcher(line);
|
|
if (matcher.matches()) {
|
|
interestingLines.add(line);
|
|
}
|
|
}
|
|
}
|
|
return interestingLines;
|
|
}
|
|
|
|
private static void runJstackMixedInLoop(LingeredApp app) throws Exception {
|
|
for (int i = 0; i < MAX_ITERATIONS; i++) {
|
|
JDKToolLauncher launcher = JDKToolLauncher
|
|
.createUsingTestJDK("jhsdb");
|
|
launcher.addVMArgs(Utils.getTestJavaOpts());
|
|
launcher.addToolArg("jstack");
|
|
launcher.addToolArg("--mixed");
|
|
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(LingeredAppWithNativeMethod.THREAD_NAME);
|
|
if (isFibAndAlignedAddress(out.asLines())) {
|
|
System.out.println("DEBUG: Test triggered interesting condition.");
|
|
out.shouldNotContain("sun.jvm.hotspot.debugger.UnmappedAddressException:");
|
|
System.out.println("DEBUG: Test PASSED.");
|
|
return; // If we've reached here, all is well.
|
|
}
|
|
System.out.println("DEBUG: Iteration: " + (i + 1)
|
|
+ " - Test didn't trigger interesting condition.");
|
|
out.shouldNotContain("sun.jvm.hotspot.debugger.UnmappedAddressException:");
|
|
}
|
|
System.out.println("DEBUG: Test didn't trigger interesting condition " +
|
|
"but no UnmappedAddressException was thrown. PASS!");
|
|
}
|
|
|
|
public static void main(String... args) throws Exception {
|
|
SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
|
|
LingeredApp app = null;
|
|
|
|
try {
|
|
// Needed for LingeredApp 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 LingeredAppWithNativeMethod();
|
|
LingeredApp.startAppExactJvmOpts(app, vmArgs);
|
|
System.out.println("Started LingeredApp with pid " + app.getPid());
|
|
runJstackMixedInLoop(app);
|
|
System.out.println("Test Completed");
|
|
} catch (Throwable e) {
|
|
e.printStackTrace();
|
|
throw e;
|
|
} finally {
|
|
LingeredApp.stopApp(app);
|
|
}
|
|
}
|
|
}
|