Path: blob/master/test/jdk/sun/tools/jhsdb/JShellHeapDumpTest.java
66644 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 822571526* @requires vm.hasSA27* @library /test/lib28* @compile JShellHeapDumpTest.java29* @run main/timeout=240 JShellHeapDumpTest30*/3132import static jdk.test.lib.Asserts.assertTrue;3334import java.io.IOException;35import java.io.File;36import java.util.List;37import java.util.Arrays;38import java.util.Map;3940import jdk.test.lib.Utils;41import jdk.test.lib.hprof.parser.HprofReader;42import jdk.test.lib.JDKToolLauncher;43import jdk.test.lib.JDKToolFinder;44import jdk.test.lib.process.OutputAnalyzer;45import jdk.test.lib.process.ProcessTools;46import jdk.test.lib.SA.SATestUtils;4748import jdk.jshell.JShell;4950public class JShellHeapDumpTest {5152static Process jShellProcess;53static boolean doSleep = true; // By default do a short sleep when app starts up5455public static void launch(String expectedMessage, List<String> toolArgs)56throws IOException {5758try {59launchJshell();60long jShellPID = jShellProcess.pid();6162System.out.println("Starting " + toolArgs.get(0) + " against " + jShellPID);63JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");64launcher.addVMArgs(Utils.getFilteredTestJavaOpts("-Xcomp"));6566for (String cmd : toolArgs) {67launcher.addToolArg(cmd);68}6970launcher.addToolArg("--pid=" + Long.toString(jShellPID));7172ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher);73OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);74System.out.println("jhsdb jmap stdout:");75System.out.println(output.getStdout());76System.out.println("jhsdb jmap stderr:");77System.out.println(output.getStderr());78System.out.println("###### End of all output:");79output.shouldHaveExitValue(0);80} catch (Exception ex) {81throw new RuntimeException("Test ERROR " + ex, ex);82} finally {83if (jShellProcess.isAlive()) {84System.out.println("Destroying jshell");85jShellProcess.destroy();86System.out.println("Jshell destroyed");87} else {88System.out.println("Jshell not alive");89}90}91}9293public static void launch(String expectedMessage, String... toolArgs)94throws IOException {9596launch(expectedMessage, Arrays.asList(toolArgs));97}9899/* Returns false if the attempt should be retried. */100public static boolean printStackTraces(String file, boolean allowRetry) throws IOException {101try {102String output = HprofReader.getStack(file, 0);103// We only require JShellToolProvider to be in the output if we did the104// short sleep. If we did not, the java process may not have executed far105// enough along to even start the main thread.106if (doSleep && !output.contains("JShellToolProvider")) {107// This check will very rarely fail due to not be able to get the stack trace108// of the main thread do to it actively executing. See JDK-8269556. We retry once109// if that happens. This failure is so rare that this should be enough to make it110// extremely unlikely that we ever see this test fail again for this reason.111if (!allowRetry) {112throw new RuntimeException("'JShellToolProvider' missing from stdout/stderr");113} else {114System.out.println("'JShellToolProvider' missing. Allow one retry.");115return true; // Allow one retry116}117}118} catch (Exception ex) {119throw new RuntimeException("Test ERROR " + ex, ex);120}121return false;122}123124/* Returns false if the attempt should be retried. */125public static boolean testHeapDump(boolean allowRetry) throws IOException {126File hprofFile = new File("jhsdb.jmap.heap." +127System.currentTimeMillis() + ".hprof");128if (hprofFile.exists()) {129hprofFile.delete();130}131132launch("heap written to", "jmap",133"--binaryheap", "--dumpfile=" + hprofFile.getAbsolutePath());134135assertTrue(hprofFile.exists() && hprofFile.isFile(),136"Could not create dump file " + hprofFile.getAbsolutePath());137138boolean retry = printStackTraces(hprofFile.getAbsolutePath(), allowRetry);139140System.out.println("hprof file size: " + hprofFile.length());141hprofFile.delete();142143return retry;144}145146public static void launchJshell() throws IOException {147System.out.println("Starting Jshell");148long startTime = System.currentTimeMillis();149try {150ProcessBuilder pb = new ProcessBuilder(JDKToolFinder.getTestJDKTool("jshell"));151jShellProcess = ProcessTools.startProcess("JShell", pb,152s -> { // warm-up predicate153return s.contains("Welcome to JShell");154});155} catch (Exception ex) {156throw new RuntimeException("Test ERROR " + ex, ex);157}158159long elapsedTime = System.currentTimeMillis() - startTime;160System.out.println("Jshell Started in " + elapsedTime + "ms");161162// Give jshell a chance to fully start up. This makes SA more stable for the jmap dump.163try {164if (doSleep) {165Thread.sleep(4000);166}167} catch (Exception e) {168}169}170171public static void main(String[] args) throws Exception {172SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.173if (args.length == 1) {174if (args[0].equals("nosleep")) {175doSleep = false;176} else {177throw new RuntimeException("Invalid arg: " + args[0]);178}179} else if (args.length != 0) {180throw new RuntimeException("Too many args: " + args.length);181}182183boolean retry = testHeapDump(true);184// In case of rare failure to find 'JShellToolProvider' in the output, allow one retry.185if (retry) {186testHeapDump(false);187}188189// The test throws RuntimeException on error.190// IOException is thrown if Jshell can't start because of some bad191// environment condition192System.out.println("Test PASSED");193}194}195196197