Mon, 23 Sep 2019 20:26:18 +0200
8196969: JTreg Failure: serviceability/sa/ClhsdbJstack.java causes NPE
Summary: Account for serialized null scopes in NMethod
Reviewed-by: aph, never, andrew
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Thu May 14 08:48:36 2020 +0200 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Mon Sep 23 20:26:18 2019 +0200 1.3 @@ -336,12 +336,17 @@ 1.4 /** This is only for use by the debugging system, and is only 1.5 intended for use in the topmost frame, where we are not 1.6 guaranteed to be at a PC for which we have a PCDesc. It finds 1.7 - the PCDesc with realPC closest to the current PC. */ 1.8 + the PCDesc with realPC closest to the current PC that has 1.9 + a valid scope decode offset. */ 1.10 public PCDesc getPCDescNearDbg(Address pc) { 1.11 PCDesc bestGuessPCDesc = null; 1.12 long bestDistance = 0; 1.13 for (Address p = scopesPCsBegin(); p.lessThan(scopesPCsEnd()); p = p.addOffsetTo(pcDescSize)) { 1.14 PCDesc pcDesc = new PCDesc(p); 1.15 + if (pcDesc.getScopeDecodeOffset() == DebugInformationRecorder.SERIALIZED_NULL) { 1.16 + // We've observed a serialized null decode offset. Ignore this PcDesc. 1.17 + continue; 1.18 + } 1.19 // In case pc is null 1.20 long distance = -pcDesc.getRealPC(this).minus(pc); 1.21 if ((bestGuessPCDesc == null) ||
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/serviceability/sa/ClhsdbJstackXcompStress.java Mon Sep 23 20:26:18 2019 +0200 2.3 @@ -0,0 +1,107 @@ 2.4 +/* 2.5 + * Copyright (c) 2019, Red Hat Inc. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +import java.util.ArrayList; 2.28 +import java.util.Arrays; 2.29 +import java.util.List; 2.30 +import java.util.regex.Matcher; 2.31 +import java.util.regex.Pattern; 2.32 +import java.util.stream.Collectors; 2.33 + 2.34 +import jdk.test.lib.JDKToolLauncher; 2.35 +import jdk.test.lib.Utils; 2.36 +import jdk.test.lib.apps.LingeredApp; 2.37 +import jdk.test.lib.process.OutputAnalyzer; 2.38 + 2.39 +/** 2.40 + * @bug 8196969 2.41 + * @requires vm.hasSAandCanAttach 2.42 + * @library /test/lib 2.43 + * @run main/othervm ClhsdbJstackXcompStress 2.44 + */ 2.45 +public class ClhsdbJstackXcompStress { 2.46 + 2.47 + private static final int MAX_ITERATIONS = 20; 2.48 + private static final boolean DEBUG = false; 2.49 + 2.50 + private static boolean isMatchCompiledFrame(List<String> output) { 2.51 + List<String> filtered = output.stream().filter( s -> s.contains("Compiled frame")) 2.52 + .collect(Collectors.toList()); 2.53 + System.out.println("DEBUG: " + filtered); 2.54 + return !filtered.isEmpty() && 2.55 + filtered.stream().anyMatch( s -> s.contains("LingeredAppWithRecComputation") ); 2.56 + } 2.57 + 2.58 + private static void runJstackInLoop(LingeredApp app) throws Exception { 2.59 + boolean anyMatchedCompiledFrame = false; 2.60 + for (int i = 0; i < MAX_ITERATIONS; i++) { 2.61 + JDKToolLauncher launcher = JDKToolLauncher 2.62 + .createUsingTestJDK("jhsdb"); 2.63 + launcher.addToolArg("jstack"); 2.64 + launcher.addToolArg("--pid"); 2.65 + launcher.addToolArg(Long.toString(app.getPid())); 2.66 + 2.67 + ProcessBuilder pb = new ProcessBuilder(); 2.68 + pb.command(launcher.getCommand()); 2.69 + Process jhsdb = pb.start(); 2.70 + OutputAnalyzer out = new OutputAnalyzer(jhsdb); 2.71 + 2.72 + jhsdb.waitFor(); 2.73 + 2.74 + if (DEBUG) { 2.75 + System.out.println(out.getStdout()); 2.76 + System.err.println(out.getStderr()); 2.77 + } 2.78 + 2.79 + out.stderrShouldBeEmpty(); // NPE's are reported on the err stream 2.80 + out.stdoutShouldNotContain("Error occurred during stack walking:"); 2.81 + out.stdoutShouldContain(LingeredAppWithRecComputation.THREAD_NAME); 2.82 + List<String> stdoutList = Arrays.asList(out.getStdout().split("\\R")); 2.83 + anyMatchedCompiledFrame = anyMatchedCompiledFrame || isMatchCompiledFrame(stdoutList); 2.84 + } 2.85 + if (!anyMatchedCompiledFrame) { 2.86 + throw new RuntimeException("Expected jstack output to contain 'Compiled frame'"); 2.87 + } 2.88 + System.out.println("DEBUG: jhsdb jstack did not throw NPE, as expected."); 2.89 + } 2.90 + 2.91 + public static void main(String... args) throws Exception { 2.92 + LingeredApp app = null; 2.93 + try { 2.94 + List<String> vmArgs = List.of("-Xcomp", 2.95 + "-XX:CompileCommand=dontinline,LingeredAppWithRecComputation.factorial", 2.96 + "-XX:CompileCommand=compileonly,LingeredAppWithRecComputation.testLoop", 2.97 + "-XX:CompileCommand=compileonly,LingeredAppWithRecComputation.factorial"); 2.98 + app = new LingeredAppWithRecComputation(); 2.99 + LingeredApp.startApp(vmArgs, app); 2.100 + System.out.println("Started LingeredAppWithRecComputation with pid " + app.getPid()); 2.101 + runJstackInLoop(app); 2.102 + System.out.println("Test Completed"); 2.103 + } catch (Throwable e) { 2.104 + e.printStackTrace(); 2.105 + throw e; 2.106 + } finally { 2.107 + LingeredApp.stopApp(app); 2.108 + } 2.109 + } 2.110 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/serviceability/sa/LingeredAppWithRecComputation.java Mon Sep 23 20:26:18 2019 +0200 3.3 @@ -0,0 +1,67 @@ 3.4 +/* 3.5 + * Copyright (c) 2019, Red Hat Inc. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +import jdk.test.lib.apps.LingeredApp; 3.28 + 3.29 +public class LingeredAppWithRecComputation extends LingeredApp { 3.30 + 3.31 + public static final String THREAD_NAME = "LingeredAppWithRecComputation.factorial()"; 3.32 + 3.33 + private long factorial(int n) { 3.34 + if (n <= 1) { 3.35 + return 1; 3.36 + } 3.37 + if (n == 2) { 3.38 + return 2; 3.39 + } 3.40 + return n * factorial(n - 1); 3.41 + } 3.42 + 3.43 + public void testLoop() { 3.44 + long result = 0; 3.45 + long[] lastNResults = new long[20]; 3.46 + int i = 0; 3.47 + int j = 0; 3.48 + while (true) { 3.49 + result = factorial(i); 3.50 + lastNResults[j] = result; 3.51 + if (i % 12 == 0) { 3.52 + i = -1; // reset i 3.53 + } 3.54 + if (j % 19 == 0) { 3.55 + j = -1; // reset j 3.56 + } 3.57 + i++; j++; 3.58 + } 3.59 + } 3.60 + 3.61 + public static void main(String args[]) { 3.62 + LingeredAppWithRecComputation app = new LingeredAppWithRecComputation(); 3.63 + Thread factorial = new Thread(() -> { 3.64 + app.testLoop(); 3.65 + }); 3.66 + factorial.setName(THREAD_NAME); 3.67 + factorial.start(); 3.68 + LingeredApp.main(args); 3.69 + } 3.70 + }