Projects
Mega:24.09
openjdk-1.8.0
_service:tar_scm:add-appcds-test-case.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:add-appcds-test-case.patch of Package openjdk-1.8.0
diff --git a/hotspot/test/runtime/appcds/AppCDSOptions.java b/hotspot/test/runtime/appcds/AppCDSOptions.java new file mode 100644 index 00000000..f5ebb5d5 --- /dev/null +++ b/hotspot/test/runtime/appcds/AppCDSOptions.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, 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. + * + */ + +// This class represents options used for +// during creation of the archive and/or running JVM with archive + +import com.oracle.java.testlibrary.cds.CDSOptions; + +public class AppCDSOptions extends CDSOptions { + public String appJar; + + // Application classes to be archived + public String[] appClasses; + + public AppCDSOptions setAppJar(String appJar) { + this.appJar = appJar; + return this; + } + + public AppCDSOptions setAppClasses(String[] appClasses) { + this.appClasses = appClasses; + return this; + } + +} diff --git a/hotspot/test/runtime/appcds/AppendClasspath.java b/hotspot/test/runtime/appcds/AppendClasspath.java new file mode 100644 index 00000000..7ebe7f62 --- /dev/null +++ b/hotspot/test/runtime/appcds/AppendClasspath.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, 2018, 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. + * + */ + +/* + * @test + * @summary At run time, it is OK to append new elements to the classpath that was used at dump time. + * @library /testlibrary + * @compile test-classes/Hello.java + * @compile test-classes/HelloMore.java + * @run main AppendClasspath + */ + +import java.io.File; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class AppendClasspath { + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + System.out.println("appJar = "); + System.out.println(appJar); + String appJar2 = JarBuilder.build("AppendClasspath_HelloMore", "HelloMore"); + System.out.println("appJar2 = "); + System.out.println(appJar2); + // Dump an archive with a specified JAR file in -classpath + TestCommon.testDump(appJar, TestCommon.list("Hello")); + + // PASS: 1) runtime with classpath containing the one used in dump time + TestCommon.run( + "-cp", appJar + File.pathSeparator + appJar2, + "HelloMore") + .assertNormalExit(); + + // PASS: 2) runtime with classpath different from the one used in dump time + TestCommon.run( + "-cp", appJar2 + File.pathSeparator + appJar, + "HelloMore"); + + // PASS: 3) runtime with classpath part of the one used in dump time + TestCommon.testDump(appJar + File.pathSeparator + appJar2, + TestCommon.list("Hello")); + TestCommon.run( + "-cp", appJar2, + "Hello"); + + // PASS: 4) runtime with same set of jar files in the classpath but + // with different order + TestCommon.run( + "-cp", appJar2 + File.pathSeparator + appJar, + "HelloMore"); + } +} + diff --git a/hotspot/test/runtime/appcds/CaseSensitiveClassPath.java b/hotspot/test/runtime/appcds/CaseSensitiveClassPath.java new file mode 100644 index 00000000..689d2a17 --- /dev/null +++ b/hotspot/test/runtime/appcds/CaseSensitiveClassPath.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, 2018, 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. + * + */ + + +/* + * @test + * @summary Test case sensitive aspect of comparing class paths + * between dump time and archive use time + * @library /testlibrary + * @compile test-classes/Hello.java + * @run main CaseSensitiveClassPath + */ + +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.OutputAnalyzer; + + +// Excluded from running on MAC: a more comprehensive case sensitivity detection +// and fix mechanism is needed, which is planned to be implemented in the future. +public class CaseSensitiveClassPath { + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String appJarUpper = appJar.replace("hello", "Hello"); + + OutputAnalyzer out = TestCommon.dump(appJar, TestCommon.list("Hello")); + TestCommon.checkDump(out); + + Path jarPath = Paths.get(appJar); + Path jarPathUpper = null; + + boolean fileExists = false; + try { + jarPathUpper = Files.createFile(Paths.get(appJarUpper)); + } catch (FileAlreadyExistsException faee) { + fileExists = true; + } + + if (!fileExists) { + try { + Files.copy(jarPath, jarPathUpper, StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + throw new java.lang.RuntimeException( + "Failed copying file from " + appJar + " to " + appJarUpper + ".", e); + } + } else { + jarPathUpper = Paths.get(appJarUpper); + } + boolean isSameFile = Files.isSameFile(jarPath, jarPathUpper); + + TestCommon.run("-cp", appJarUpper, "Hello", "-Xlog:class+path=info", + "-Xlog:cds") + .ifNoMappingFailure(output -> { + output.shouldContain("Hello World"); + }); + } +} + diff --git a/hotspot/test/runtime/appcds/CommandLineFlagCombo.java b/hotspot/test/runtime/appcds/CommandLineFlagCombo.java new file mode 100644 index 00000000..7f7ca7bf --- /dev/null +++ b/hotspot/test/runtime/appcds/CommandLineFlagCombo.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, 2018, 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. + * + */ + +/* + * @test CommandLineFlagCombo + * @requires (vm.gc=="null") + * @summary Test command line flag combinations that + * could likely affect the behaviour of AppCDS + * @library /testlibrary /testlibrary/whitebox + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @compile test-classes/Hello.java + * @run main/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CommandLineFlagCombo + */ + +import com.oracle.java.testlibrary.BuildHelper; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.OutputAnalyzer; + +import sun.hotspot.code.Compiler; + +public class CommandLineFlagCombo { + + // shared base address test table + private static final String[] testTable = { + "-XX:+UseG1GC", "-XX:+UseSerialGC", "-XX:+UseParallelGC", "-XX:+UseConcMarkSweepGC", + "-XX:+FlightRecorder", + "-XX:+UseLargePages", // may only take effect on machines with large-pages + "-XX:+UseCompressedClassPointers", + "-XX:+UseCompressedOops", + "-XX:ObjectAlignmentInBytes=16", + "-XX:ObjectAlignmentInBytes=32", + "-XX:ObjectAlignmentInBytes=64" + }; + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + String classList[] = {"Hello"}; + + for (String testEntry : testTable) { + System.out.println("CommandLineFlagCombo = " + testEntry); + + if (skipTestCase(testEntry)) + continue; + + OutputAnalyzer dumpOutput = TestCommon.dump(appJar, classList, testEntry); + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, testEntry, "Hello"); + TestCommon.checkExec(execOutput, "Hello World"); + } + + for (int i=0; i<2; i++) { + String g1Flag, serialFlag; + + // Interned strings are supported only with G1GC. However, we should not crash if: + // 0: archive has shared strings, but run time doesn't support shared strings + // 1: archive has no shared strings, but run time supports shared strings + + String dump_g1Flag = "-XX:" + (i == 0 ? "+" : "-") + "UseG1GC"; + String run_g1Flag = "-XX:" + (i != 0 ? "+" : "-") + "UseG1GC"; + String dump_serialFlag = "-XX:" + (i != 0 ? "+" : "-") + "UseSerialGC"; + String run_serialFlag = "-XX:" + (i == 0 ? "+" : "-") + "UseSerialGC"; + + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, classList, dump_g1Flag, dump_serialFlag); + + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, run_g1Flag, run_serialFlag, "Hello"); + TestCommon.checkExec(execOutput, "Hello World"); + } + } + + private static boolean skipTestCase(String testEntry) throws Exception { + if (Platform.is32bit()) + { + if (testEntry.equals("-XX:+UseCompressedOops") || + testEntry.equals("-XX:+UseCompressedClassPointers") || + testEntry.contains("ObjectAlignmentInBytes") ) + { + System.out.println("Test case not applicable on 32-bit platforms"); + return true; + } + } + + if (Compiler.isGraalEnabled() && testEntry.equals("-XX:+UseConcMarkSweepGC")) + { + System.out.println("Graal does not support CMS"); + return true; + } + + return false; + } +} + diff --git a/hotspot/test/runtime/appcds/CommandLineFlagComboNegative.java b/hotspot/test/runtime/appcds/CommandLineFlagComboNegative.java new file mode 100644 index 00000000..4fb965ab --- /dev/null +++ b/hotspot/test/runtime/appcds/CommandLineFlagComboNegative.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014, 2018, 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. + * + */ + +/* + * @test CommandLineFlagComboNegative + * @summary Test command line flag combinations that differ between + * the dump and execute steps, in such way that they cause errors + * E.g. use compressed oops for creating and archive, but then + * execute w/o compressed oops + * @library /testlibrary + * @compile test-classes/Hello.java + * @run main CommandLineFlagComboNegative + */ + +import java.util.ArrayList; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class CommandLineFlagComboNegative { + + private class TestVector { + public String testOptionForDumpStep; + public String testOptionForExecuteStep; + public String expectedErrorMsg; + public int expectedErrorCode; + + public TestVector(String testOptionForDumpStep, String testOptionForExecuteStep, + String expectedErrorMsg, int expectedErrorCode) { + this.testOptionForDumpStep=testOptionForDumpStep; + this.testOptionForExecuteStep=testOptionForExecuteStep; + this.expectedErrorMsg=expectedErrorMsg; + this.expectedErrorCode=expectedErrorCode; + } + } + + private ArrayList<TestVector> testTable = new ArrayList<TestVector>(); + + private void initTestTable() { + // These options are not applicable on 32-bit platforms + if (Platform.is64bit()) { + testTable.add( new TestVector("-XX:ObjectAlignmentInBytes=8", "-XX:ObjectAlignmentInBytes=16", + "An error has occurred while processing the shared archive file", 1) ); + testTable.add( new TestVector("-XX:ObjectAlignmentInBytes=64", "-XX:ObjectAlignmentInBytes=32", + "An error has occurred while processing the shared archive file", 1) ); + testTable.add( new TestVector("-XX:+UseCompressedOops", "-XX:-UseCompressedOops", + "Class data sharing is inconsistent with other specified options", 1) ); + testTable.add( new TestVector("-XX:+UseCompressedClassPointers", "-XX:-UseCompressedClassPointers", + "Class data sharing is inconsistent with other specified options", 1) ); + } + } + + private void runTests() throws Exception + { + for (TestVector testEntry : testTable) { + System.out.println("CommandLineFlagComboNegative: dump = " + testEntry.testOptionForDumpStep); + System.out.println("CommandLineFlagComboNegative: execute = " + testEntry.testOptionForExecuteStep); + + String appJar = JarBuilder.getOrCreateHelloJar(); + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, new String[] {"Hello"}, testEntry.testOptionForDumpStep); + + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + TestCommon.run( + "-cp", appJar, + testEntry.testOptionForExecuteStep, + "Hello") + .assertAbnormalExit(output -> { + output.shouldContain(testEntry.expectedErrorMsg) + .shouldHaveExitValue(testEntry.expectedErrorCode); + }); + } + } + + public static void main(String[] args) throws Exception { + CommandLineFlagComboNegative thisClass = new CommandLineFlagComboNegative(); + thisClass.initTestTable(); + thisClass.runTests(); + } +} + diff --git a/hotspot/test/runtime/appcds/DirClasspathTest.java b/hotspot/test/runtime/appcds/DirClasspathTest.java new file mode 100644 index 00000000..e2c4e698 --- /dev/null +++ b/hotspot/test/runtime/appcds/DirClasspathTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2017, 2018, 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. + * + */ + +/* + * @test + * @summary Handling of directories in -cp is based on the classlist + * @library /testlibrary + * @compile test-classes/Hello.java + * @run main DirClasspathTest + */ + +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.OutputAnalyzer; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +public class DirClasspathTest { + private static final int MAX_PATH = 260; + + public static void main(String[] args) throws Exception { + File dir = new File(System.getProperty("user.dir")); + File emptydir = new File(dir, "emptydir"); + emptydir.mkdir(); + + ///////////////////////////////////////////////////////////////// + // The classlist only contains boot class in following test cases + ///////////////////////////////////////////////////////////////// + String bootClassList[] = {"java/lang/Object"}; + + // Empty dir in -cp: should be OK + OutputAnalyzer output; + output = TestCommon.dump(emptydir.getPath(), bootClassList); + TestCommon.checkDump(output); + + // Long path to empty dir in -cp: should be OK + Path classDir = Paths.get(System.getProperty("test.classes")); + Path destDir = classDir; + int subDirLen = MAX_PATH - classDir.toString().length() - 2; + if (subDirLen > 0) { + char[] chars = new char[subDirLen]; + Arrays.fill(chars, 'x'); + String subPath = new String(chars); + destDir = Paths.get(System.getProperty("test.classes"), subPath); + } + File longDir = destDir.toFile(); + longDir.mkdir(); + File subDir = new File(longDir, "subdir"); + subDir.mkdir(); + output = TestCommon.dump(subDir.getPath(), bootClassList); + TestCommon.checkDump(output); + + // Non-empty dir in -cp: should be OK + // <dir> is not empty because it has at least one subdirectory, i.e., <emptydir> + output = TestCommon.dump(dir.getPath(), bootClassList); + TestCommon.checkDump(output); + + // Long path to non-empty dir in -cp: should be OK + // <dir> is not empty because it has at least one subdirectory, i.e., <emptydir> + output = TestCommon.dump(longDir.getPath(), bootClassList); + TestCommon.checkDump(output); + + ///////////////////////////////////////////////////////////////// + // The classlist contains non-boot class in following test cases + ///////////////////////////////////////////////////////////////// + String appClassList[] = {"java/lang/Object", "com/sun/tools/javac/Main"}; + + // Non-empty dir in -cp: should be OK (as long as no classes were loaded from there) + output = TestCommon.dump(dir.getPath(), appClassList); + TestCommon.checkDump(output); + + // Long path to non-empty dir in -cp: should be OK (as long as no classes were loaded from there) + output = TestCommon.dump(longDir.getPath(), appClassList); + TestCommon.checkDump(output); + + ///////////////////////////////////////////////////////////////// + // Loading an app class from a directory + ///////////////////////////////////////////////////////////////// + String appClassList2[] = {"Hello", "java/lang/Object", "com/sun/tools/javac/Main"}; + // Non-empty dir in -cp: should report error if a class is loaded from it + output = TestCommon.dump(classDir.toString(), appClassList2); + output.shouldNotHaveExitValue(1); + output.shouldContain("Cannot find com/sun/tools/javac/Main"); + // Long path to non-empty dir in -cp: should report error if a class is loaded from it + File srcClass = new File(classDir.toFile(), "Hello.class"); + File destClass = new File(longDir, "Hello.class"); + Files.copy(srcClass.toPath(), destClass.toPath()); + output = TestCommon.dump(longDir.getPath(), appClassList2); + output.shouldNotHaveExitValue(1); + output.shouldContain("Cannot find Hello"); + } +} + diff --git a/hotspot/test/runtime/appcds/HelloTest.java b/hotspot/test/runtime/appcds/HelloTest.java new file mode 100644 index 00000000..c49179a1 --- /dev/null +++ b/hotspot/test/runtime/appcds/HelloTest.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +/* + * @test + * @summary Hello World test for AppCDS + * @library /testlibrary + * @compile test-classes/Hello.java + * @run main HelloTest + */ + +public class HelloTest { + public static void main(String[] args) throws Exception { + TestCommon.test(JarBuilder.getOrCreateHelloJar(), + TestCommon.list("Hello"), "Hello"); + } +} diff --git a/hotspot/test/runtime/appcds/IgnoreEmptyClassPaths.java b/hotspot/test/runtime/appcds/IgnoreEmptyClassPaths.java new file mode 100644 index 00000000..36618b17 --- /dev/null +++ b/hotspot/test/runtime/appcds/IgnoreEmptyClassPaths.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, 2018, 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. + * + */ + +/* + * @test + * @summary Test the -XX:+IgnoreEmptyClassPaths flag + * @library /testlibrary + * @compile test-classes/Hello.java + * @compile test-classes/HelloMore.java + * @run main IgnoreEmptyClassPaths + */ + +import java.io.File; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class IgnoreEmptyClassPaths { + + public static void main(String[] args) throws Exception { + String jar1 = JarBuilder.getOrCreateHelloJar(); + String jar2 = JarBuilder.build("IgnoreEmptyClassPaths_more", "HelloMore"); + + String sep = File.pathSeparator; + String cp_dump = jar1 + sep + jar2 + sep; + String cp_exec = sep + jar1 + sep + sep + jar2 + sep; + + TestCommon.testDump(cp_dump, TestCommon.list("Hello", "HelloMore"), + "-XX:+TraceClassPaths", "-XX:+IgnoreEmptyClassPaths"); + + TestCommon.run( + "-verbose:class", + "-cp", cp_exec, + "-XX:+IgnoreEmptyClassPaths", // should affect classpath even if placed after the "-cp" argument + "-XX:+TraceClassPaths", + "HelloMore") + .assertNormalExit(); + } +} diff --git a/hotspot/test/runtime/appcds/JarBuilder.java b/hotspot/test/runtime/appcds/JarBuilder.java new file mode 100644 index 00000000..e06ab2bc --- /dev/null +++ b/hotspot/test/runtime/appcds/JarBuilder.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2015, 2018, 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. + * + */ + +/* + * @summary Simple jar builder + * Input: jarName className1 className2 ... + * do not specify extensions, just the names + * E.g. prot_domain ProtDomainA ProtDomainB + * Output: A jar containing compiled classes, placed in a test classes folder + * @library /open/test/lib + */ + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; + +import com.oracle.java.testlibrary.JDKToolFinder; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.compiler.CompilerUtils; +import sun.tools.jar.Main; + +public class JarBuilder { + // to turn DEBUG on via command line: -DJarBuilder.DEBUG=[true, TRUE] + private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("JarBuilder.DEBUG", "false")); + private static final String classDir = System.getProperty("test.classes"); + + public static String getJarFilePath(String jarName) { + return classDir + File.separator + jarName + ".jar"; + } + + // jar all files under dir, with manifest file man, with an optional versionArgs + // for generating a multi-release jar. + // The jar command is as follows: + // jar cmf \ + // <path to output jar> <path to the manifest file>\ + // -C <path to the base classes> .\ + // --release 9 -C <path to the versioned classes> . + // the last line begins with "--release" corresponds to the optional versionArgs. + public static void build(String jarName, File dir, String man, String...versionArgs) + throws Exception { + ArrayList<String> args = new ArrayList<String>(); + if (man != null) { + args.add("cfm"); + } else { + args.add("cf"); + } + args.add(classDir + File.separator + jarName + ".jar"); + if (man != null) { + args.add(man); + } + args.add("-C"); + args.add(dir.getAbsolutePath()); + args.add("."); + for (String verArg : versionArgs) { + args.add(verArg); + } + createJar(args); + } + + public static String build(String jarName, String...classNames) + throws Exception { + + return createSimpleJar(classDir, getJarFilePath(jarName), classNames); + } + + public static String build(boolean classesInWorkDir, String jarName, String...classNames) + throws Exception { + if (classesInWorkDir) { + return createSimpleJar(".", getJarFilePath(jarName), classNames); + } else { + return build(jarName, classNames); + } + } + + + public static String buildWithManifest(String jarName, String manifest, + String jarClassesDir, String...classNames) throws Exception { + String jarPath = getJarFilePath(jarName); + ArrayList<String> args = new ArrayList<String>(); + args.add("cvfm"); + args.add(jarPath); + args.add(System.getProperty("test.src") + File.separator + "test-classes" + + File.separator + manifest); + addClassArgs(args, jarClassesDir, classNames); + createJar(args); + + return jarPath; + } + + + // Execute: jar uvf $jarFile -C $dir . + static void update(String jarFile, String dir) throws Exception { + String jarExe = JDKToolFinder.getJDKTool("jar"); + + ArrayList<String> args = new ArrayList<>(); + args.add(jarExe); + args.add("uvf"); + args.add(jarFile); + args.add("-C"); + args.add(dir); + args.add("."); + + executeProcess(args.toArray(new String[1])); + } + + + private static String createSimpleJar(String jarclassDir, String jarName, + String[] classNames) throws Exception { + + ArrayList<String> args = new ArrayList<String>(); + args.add("cf"); + args.add(jarName); + addClassArgs(args, jarclassDir, classNames); + createJar(args); + + return jarName; + } + + private static void addClassArgs(ArrayList<String> args, String jarclassDir, + String[] classNames) { + + for (String name : classNames) { + args.add("-C"); + args.add(jarclassDir); + args.add(name + ".class"); + } + } + + public static void createModularJar(String jarPath, + String classesDir, + String mainClass) throws Exception { + ArrayList<String> argList = new ArrayList<String>(); + argList.add("--create"); + argList.add("--file=" + jarPath); + if (mainClass != null) { + argList.add("--main-class=" + mainClass); + } + argList.add("-C"); + argList.add(classesDir); + argList.add("."); + createJar(argList); + } + + private static void createJar(ArrayList<String> args) { + if (DEBUG) printIterable("createJar args: ", args); + + Main jarTool = new Main(System.out, System.err, "jar"); + if (!jarTool.run(args.toArray(new String[1]))) { + throw new RuntimeException("jar operation failed"); + } + } + + // Many AppCDS tests use the same simple "Hello.jar" which contains + // simple Hello.class and does not specify additional attributes. + // For this common use case, use this method to get the jar path. + // The method will check if the jar already exists + // (created by another test or test run), and will create the jar + // if it does not exist + public static String getOrCreateHelloJar() throws Exception { + String jarPath = getJarFilePath("hello"); + + File jarFile = new File(jarPath); + if (jarFile.exists()) { + return jarPath; + } else { + return build("hello", "Hello"); + } + } + + public static void compile(String dstPath, String source, String... extraArgs) throws Exception { + ArrayList<String> args = new ArrayList<String>(); + args.add(JDKToolFinder.getCompileJDKTool("javac")); + args.add("-d"); + args.add(dstPath); + if (extraArgs != null) { + for (String s : extraArgs) { + args.add(s); + } + } + args.add(source); + + if (DEBUG) printIterable("compile args: ", args); + + ProcessBuilder pb = new ProcessBuilder(args); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } + + public static void compileModule(Path src, + Path dest, + String modulePathArg // arg to --module-path + ) throws Exception { + boolean compiled = false; + if (modulePathArg == null) { + compiled = CompilerUtils.compile(src, dest); + } else { + compiled = CompilerUtils.compile(src, dest, + "--module-path", modulePathArg); + } + if (!compiled) { + throw new RuntimeException("module did not compile"); + } + } + + + public static void signJar() throws Exception { + String keyTool = JDKToolFinder.getJDKTool("keytool"); + String jarSigner = JDKToolFinder.getJDKTool("jarsigner"); + String classDir = System.getProperty("test.classes"); + String FS = File.separator; + + executeProcess(keyTool, + "-genkey", "-keystore", "./keystore", "-alias", "mykey", + "-storepass", "abc123", "-keypass", "abc123", + "-dname", "CN=jvmtest") + .shouldHaveExitValue(0); + + executeProcess(jarSigner, + "-keystore", "./keystore", "-storepass", "abc123", "-keypass", + "abc123", "-signedjar", classDir + FS + "signed_hello.jar", + classDir + FS + "hello.jar", "mykey") + .shouldHaveExitValue(0); + } + + private static OutputAnalyzer executeProcess(String... cmds) + throws Exception { + + JarBuilder.printArray("executeProcess: ", cmds); + return ProcessTools.executeProcess(new ProcessBuilder(cmds)); + } + + // diagnostic + public static void printIterable(String msg, Iterable<String> l) { + StringBuilder sum = new StringBuilder(); + for (String s : l) { + sum.append(s).append(' '); + } + System.out.println(msg + sum.toString()); + } + + public static void printArray(String msg, String[] l) { + StringBuilder sum = new StringBuilder(); + for (String s : l) { + sum.append(s).append(' '); + } + System.out.println(msg + sum.toString()); + } +} diff --git a/hotspot/test/runtime/appcds/MismatchedUseAppCDS.java b/hotspot/test/runtime/appcds/MismatchedUseAppCDS.java new file mode 100644 index 00000000..7173d6c9 --- /dev/null +++ b/hotspot/test/runtime/appcds/MismatchedUseAppCDS.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, 2018, 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. + * + */ + +/* + * @test + * @summary Try different combination of mismatched UseAppCDS between dump time and run time. + * @library /testlibrary /testlibrary/whitebox + * @compile test-classes/CheckIfShared.java + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main MismatchedUseAppCDS + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class MismatchedUseAppCDS { + public static void main(String[] args) throws Exception { + String wbJar = JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + + String appJar = JarBuilder.build("MismatchedUseAppCDS", "CheckIfShared"); + + OutputAnalyzer output; + + // (1): dump with -XX:+UseAppCDS, but run with -XX:-UseAppCDS + TestCommon.testDump(appJar, TestCommon.list("CheckIfShared"), + // command-line arguments ... + "-XX:+UseAppCDS", + use_whitebox_jar); + + output = TestCommon.exec(appJar, + // command-line arguments ... + use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckIfShared", "false"); + TestCommon.checkExec(output); + + // (2): dump with -XX:-UseAppCDS, but run with -XX:+UseAppCDS + TestCommon.testDump(appJar, TestCommon.list("CheckIfShared"), + // command-line arguments ... + "-XX:+UseAppCDS", + use_whitebox_jar); + + output = TestCommon.exec(appJar, + // command-line arguments ... + use_whitebox_jar, + "-XX:+UseAppCDS", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckIfShared", "true"); + TestCommon.checkExec(output); + } +} + diff --git a/hotspot/test/runtime/appcds/MissingSuperTest.java b/hotspot/test/runtime/appcds/MissingSuperTest.java new file mode 100644 index 00000000..33a860b4 --- /dev/null +++ b/hotspot/test/runtime/appcds/MissingSuperTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +/* + * @test + * @summary When super class is missing during dumping, no crash should happen. + * @library /testlibrary + * @compile test-classes/MissingSuper.java + * @run main MissingSuperTest + */ + +public class MissingSuperTest { + + public static void main(String[] args) throws Exception { + // The classes "MissingSuperSup" and "MissingSuperIntf" are intentionally not + // included into the jar to provoke the test condition + JarBuilder.build("missing_super", "MissingSuper", + "MissingSuperSub", "MissingSuperImpl"); + + String appJar = TestCommon.getTestJar("missing_super.jar"); + TestCommon.test(appJar, TestCommon.list("MissingSuper", + "MissingSuperSub", + "MissingSuperImpl"), + "MissingSuper"); + } +} diff --git a/hotspot/test/runtime/appcds/PackageSealing.java b/hotspot/test/runtime/appcds/PackageSealing.java new file mode 100644 index 00000000..6c915085 --- /dev/null +++ b/hotspot/test/runtime/appcds/PackageSealing.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +/* + * @test + * @summary AppCDS handling of package. + * @library /testlibrary + * @compile test-classes/C1.java + * @compile test-classes/C2.java + * @compile test-classes/PackageSealingTest.java + * @run main PackageSealing + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class PackageSealing { + public static void main(String args[]) throws Exception { + String[] classList = {"sealed/pkg/C1", "pkg/C2", "PackageSealingTest"}; + String appJar = ClassFileInstaller.writeJar("pkg_seal.jar", + ClassFileInstaller.Manifest.fromSourceFile("test-classes/package_seal.mf"), + "PackageSealingTest", "sealed/pkg/C1", "pkg/C2"); + + // test shared package from -cp path + TestCommon.testDump(appJar, TestCommon.list(classList)); + OutputAnalyzer output; + output = TestCommon.exec(appJar, "PackageSealingTest"); + TestCommon.checkExec(output); + + // test shared package from -Xbootclasspath/a + TestCommon.dump(appJar, TestCommon.list(classList), + "-Xbootclasspath/a:" + appJar); + output = TestCommon.exec(appJar, "-Xbootclasspath/a:" + appJar, "PackageSealingTest"); + TestCommon.checkExec(output); + } +} diff --git a/hotspot/test/runtime/appcds/ParallelLoad2.java b/hotspot/test/runtime/appcds/ParallelLoad2.java new file mode 100644 index 00000000..5709be6a --- /dev/null +++ b/hotspot/test/runtime/appcds/ParallelLoad2.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +/* + * @test + * @summary Load app classes from CDS archive in parallel threads. Similar to ParallelLoad.java, but each class in its own JAR + * @library /testlibrary + * @compile test-classes/ParallelLoad.java + * @compile test-classes/ParallelClasses.java + * @run main ParallelLoad2 + */ + +import java.io.File; + +public class ParallelLoad2 { + public static int MAX_CLASSES = 40; + public static void main(String[] args) throws Exception { + JarBuilder.build("parallel_load2", "ParallelLoad", "ParallelLoadThread", "ParallelLoadWatchdog"); + for (int i=0; i<MAX_CLASSES; i++) { + JarBuilder.build("parallel_load2_" + i, "ParallelClass" + i); + } + + String cp = TestCommon.getTestJar("parallel_load2.jar"); + for (int i=0; i<MAX_CLASSES; i++) { + cp += File.pathSeparator + TestCommon.getTestJar("parallel_load2_" + i + ".jar"); + } + + String[] class_list = new String[MAX_CLASSES + 2]; + for (int i=0; i<MAX_CLASSES; i++) { + class_list[i] = "ParallelClass" + i; + } + class_list[class_list.length - 1] = "ParallelLoad"; + class_list[class_list.length - 2] = "ParallelLoadThread"; + + TestCommon.test(cp, class_list, + "ParallelLoad"); + } +} + diff --git a/hotspot/test/runtime/appcds/ParallelLoadTest.java b/hotspot/test/runtime/appcds/ParallelLoadTest.java new file mode 100644 index 00000000..92d17a47 --- /dev/null +++ b/hotspot/test/runtime/appcds/ParallelLoadTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +/* + * @test + * @summary Load app classes from CDS archive in parallel threads + * @library /testlibrary + * @compile test-classes/ParallelLoad.java + * @compile test-classes/ParallelClasses.java + * @run main ParallelLoadTest + */ + +public class ParallelLoadTest { + public static final int MAX_CLASSES = 40; + + public static void main(String[] args) throws Exception { + JarBuilder.build("parallel_load", getClassList(true)); + String appJar = TestCommon.getTestJar("parallel_load.jar"); + TestCommon.test(appJar, getClassList(false), "ParallelLoad"); + } + + private static String[] getClassList(boolean includeWatchdog) { + int extra = includeWatchdog ? 3 : 2; + String[] classList = new String[MAX_CLASSES + extra]; + + int i; + for (i=0; i<MAX_CLASSES; i++) { + classList[i] = "ParallelClass" + i; + } + + classList[i++] = "ParallelLoad"; + classList[i++] = "ParallelLoadThread"; + if (includeWatchdog) + classList[i++] = "ParallelLoadWatchdog"; + + return classList; + } +} + diff --git a/hotspot/test/runtime/appcds/SharedBaseAddress.java b/hotspot/test/runtime/appcds/SharedBaseAddress.java new file mode 100644 index 00000000..b03b0876 --- /dev/null +++ b/hotspot/test/runtime/appcds/SharedBaseAddress.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +/* + * @test SharedBaseAddress + * @summary Test variety of values for SharedBaseAddress, in AppCDS mode, + * making sure VM handles normal values as well as edge values + * w/o a crash. + * @library /testlibrary + * @compile test-classes/Hello.java + * @run main/timeout=240 SharedBaseAddress + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class SharedBaseAddress { + + // shared base address test table + private static final String[] testTable = { + "1g", "8g", "64g","512g", "4t", + "32t", "128t", "0", + "1", "64k", "64M" + }; + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + + for (String testEntry : testTable) { + System.out.println("sharedBaseAddress = " + testEntry); + + OutputAnalyzer dumpOutput = TestCommon.dump( + appJar, new String[] {"Hello"}, "-XX:SharedBaseAddress=" + testEntry); + TestCommon.checkDump(dumpOutput, "Loading classes to share"); + + OutputAnalyzer execOutput = TestCommon.exec(appJar, "Hello"); + TestCommon.checkExec(execOutput, "Hello World"); + } + } +} + diff --git a/hotspot/test/runtime/appcds/TestCommon.java b/hotspot/test/runtime/appcds/TestCommon.java new file mode 100644 index 00000000..4ed416fe --- /dev/null +++ b/hotspot/test/runtime/appcds/TestCommon.java @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2014, 2018, 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 com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.cds.CDSTestUtils; +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Date; + +/** + * This is a test utility class for common AppCDS test functionality. + * + * Various methods use (String ...) for passing VM options. Note that the order + * of the VM options are important in certain cases. Many methods take arguments like + * + * (String prefix[], String suffix[], String... opts) + * + * Note that the order of the VM options is: + * + * prefix + opts + suffix + */ +public class TestCommon extends CDSTestUtils { + private static final String JSA_FILE_PREFIX = System.getProperty("user.dir") + + File.separator + "appcds-"; + + private static final SimpleDateFormat timeStampFormat = + new SimpleDateFormat("HH'h'mm'm'ss's'SSS"); + + private static final String timeoutFactor = + System.getProperty("test.timeout.factor", "1.0"); + + private static String currentArchiveName; + + // Call this method to start new archive with new unique name + public static void startNewArchiveName() { + deletePriorArchives(); + currentArchiveName = JSA_FILE_PREFIX + + timeStampFormat.format(new Date()) + ".jsa"; + } + + // Call this method to get current archive name + public static String getCurrentArchiveName() { + return currentArchiveName; + } + + public static void setCurrentArchiveName(String archiveName) { + currentArchiveName = archiveName; + } + + // Attempt to clean old archives to preserve space + // Archives are large artifacts (20Mb or more), and much larger than + // most other artifacts created in jtreg testing. + // Therefore it is a good idea to clean the old archives when they are not needed. + // In most cases the deletion attempt will succeed; on rare occasion the + // delete operation will fail since the system or VM process still holds a handle + // to the file; in such cases the File.delete() operation will silently fail, w/o + // throwing an exception, thus allowing testing to continue. + public static void deletePriorArchives() { + File dir = new File(System.getProperty("user.dir")); + String files[] = dir.list(); + for (String name : files) { + if (name.startsWith("appcds-") && name.endsWith(".jsa")) { + if (!(new File(dir, name)).delete()) + System.out.println("deletePriorArchives(): delete failed for file " + name); + } + } + } + + + // Create AppCDS archive using most common args - convenience method + // Legacy name preserved for compatibility + public static OutputAnalyzer dump(String appJar, String appClasses[], + String... suffix) throws Exception { + return createArchive(appJar, appClasses, suffix); + } + + + // Create AppCDS archive using most common args - convenience method + public static OutputAnalyzer createArchive(String appJar, String appClasses[], + String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar) + .setAppClasses(appClasses); + opts.addSuffix(suffix); + return createArchive(opts); + } + + public static String[] makeCommandLineForAppCDS(String... args) throws Exception { + return args; + } + + // Create AppCDS archive using appcds options + public static OutputAnalyzer createArchive(AppCDSOptions opts) + throws Exception { + + ArrayList<String> cmd = new ArrayList<String>(); + File classList = makeClassList(opts.appClasses); + startNewArchiveName(); + + for (String p : opts.prefix) cmd.add(p); + + if (opts.appJar != null) { + cmd.add("-cp"); + cmd.add(opts.appJar); + } else { + cmd.add("-cp"); + cmd.add("\"\""); + } + + cmd.add("-Xshare:dump"); +// cmd.add("-Xlog:cds,cds+hashtables"); comment out because it will be run by jdk1.8 + cmd.add("-XX:ExtraSharedClassListFile=" + classList.getPath()); + + if (opts.archiveName == null) + opts.archiveName = getCurrentArchiveName(); + + cmd.add("-XX:SharedArchiveFile=" + opts.archiveName); + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, makeCommandLineForAppCDS(cmdLine)); + return executeAndLog(pb, "dump"); + } + + + // Execute JVM using AppCDS archive with specified AppCDSOptions + public static OutputAnalyzer runWithArchive(AppCDSOptions opts) + throws Exception { + + ArrayList<String> cmd = new ArrayList<String>(); + + for (String p : opts.prefix) cmd.add(p); + + cmd.add("-Xshare:" + opts.xShareMode); + cmd.add("-showversion"); + cmd.add("-XX:SharedArchiveFile=" + getCurrentArchiveName()); + cmd.add("-Dtest.timeout.factor=" + timeoutFactor); + + if (opts.appJar != null) { + cmd.add("-cp"); + cmd.add(opts.appJar); + } + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, makeCommandLineForAppCDS(cmdLine)); + return executeAndLog(pb, "exec"); + } + + + public static OutputAnalyzer execCommon(String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()); + opts.addSuffix(suffix); + return runWithArchive(opts); + } + + // This is the new API for running a Java process with CDS enabled. + // See comments in the CDSTestUtils.Result class for how to use this method. + public static Result run(String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()); + opts.addSuffix(suffix); + return new Result(opts, runWithArchive(opts)); + } + + public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar); + opts.addSuffix(suffix); + return runWithArchive(opts); + } + + public static Result runWithModules(String prefix[], String upgrademodulepath, String modulepath, + String mid, String... testClassArgs) throws Exception { + AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath, + mid, testClassArgs); + return new Result(opts, runWithArchive(opts)); + } + + public static OutputAnalyzer execAuto(String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()); + opts.addSuffix(suffix).setXShareMode("auto"); + return runWithArchive(opts); + } + + public static OutputAnalyzer execOff(String... suffix) throws Exception { + AppCDSOptions opts = (new AppCDSOptions()); + opts.addSuffix(suffix).setXShareMode("off"); + return runWithArchive(opts); + } + + + private static AppCDSOptions makeModuleOptions(String prefix[], String upgrademodulepath, String modulepath, + String mid, String testClassArgs[]) { + AppCDSOptions opts = (new AppCDSOptions()); + + opts.addPrefix(prefix); + if (upgrademodulepath == null) { + opts.addSuffix("-p", modulepath, "-m", mid); + } else { + opts.addSuffix("--upgrade-module-path", upgrademodulepath, + "-p", modulepath, "-m", mid); + } + opts.addSuffix(testClassArgs); + return opts; + } + + public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath, + String mid, String... testClassArgs) + throws Exception { + AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath, + mid, testClassArgs); + return runWithArchive(opts); + } + + + // A common operation: dump, then check results + public static OutputAnalyzer testDump(String appJar, String appClasses[], + String... suffix) throws Exception { + OutputAnalyzer output = dump(appJar, appClasses, suffix); + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + return output; + } + + + /** + * Simple test -- dump and execute appJar with the given appClasses in classlist. + */ + public static OutputAnalyzer test(String appJar, String appClasses[], String... args) + throws Exception { + testDump(appJar, appClasses); + + OutputAnalyzer output = exec(appJar, args); + return checkExec(output); + } + + + public static OutputAnalyzer checkExecReturn(OutputAnalyzer output, int ret, + boolean checkContain, String... matches) throws Exception { + try { + for (String s : matches) { + if (checkContain) { + output.shouldContain(s); + } else { + output.shouldNotContain(s); + } + } + output.shouldHaveExitValue(ret); + } catch (Exception e) { + checkCommonExecExceptions(output, e); + } + + return output; + } + + + // Convenience concatenation utils + public static String[] list(String ...args) { + return args; + } + + + public static String[] list(String arg, int count) { + ArrayList<String> stringList = new ArrayList<String>(); + for (int i = 0; i < count; i++) { + stringList.add(arg); + } + + String outputArray[] = stringList.toArray(new String[stringList.size()]); + return outputArray; + } + + + public static String[] concat(String... args) { + return list(args); + } + + + public static String[] concat(String prefix[], String... extra) { + ArrayList<String> list = new ArrayList<String>(); + for (String s : prefix) { + list.add(s); + } + for (String s : extra) { + list.add(s); + } + + return list.toArray(new String[list.size()]); + } + + + // ===================== Concatenate paths + public static String concatPaths(String... paths) { + String prefix = ""; + String s = ""; + for (String p : paths) { + s += prefix; + s += p; + prefix = File.pathSeparator; + } + return s; + } + + + public static String getTestJar(String jar) { + File jarFile = CDSTestUtils.getTestArtifact(jar, true); + if (!jarFile.isFile()) { + throw new RuntimeException("Not a regular file: " + jarFile.getPath()); + } + return jarFile.getPath(); + } + + + public static String getTestDir(String d) { + File dirFile = CDSTestUtils.getTestArtifact(d, true); + if (!dirFile.isDirectory()) { + throw new RuntimeException("Not a directory: " + dirFile.getPath()); + } + return dirFile.getPath(); + } + + public static boolean checkOutputStrings(String outputString1, + String outputString2, + String split_regex) { + String[] sa1 = outputString1.split(split_regex); + String[] sa2 = outputString2.split(split_regex); + Arrays.sort(sa1); + Arrays.sort(sa2); + + int i = 0; + for (String s : sa1) { + if (!s.equals(sa2[i])) { + throw new RuntimeException(s + " is different from " + sa2[i]); + } + i ++; + } + return true; + } +} diff --git a/hotspot/test/runtime/appcds/TraceLongClasspath.java b/hotspot/test/runtime/appcds/TraceLongClasspath.java new file mode 100644 index 00000000..e25fcd37 --- /dev/null +++ b/hotspot/test/runtime/appcds/TraceLongClasspath.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, 2018, 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. + * + */ + +/* + * @test + * @summary ensure -XX:+TraceClassPaths showing entire expecting app classpath + * @library /testlibrary + * @compile test-classes/Hello.java + * @run main TraceLongClasspath + */ + +import java.io.File; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class TraceLongClasspath { + + final static String ps = File.pathSeparator; + + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.getOrCreateHelloJar(); + + String longClassPath = + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/user-patch.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/abc-startup.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/features/com.foobar.db.jdbc7-dms.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/server/lib/someapps.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/../foobar_common/modules/net.xy.batcontrib_1.1.0.0_1-0b3/lib/bat-contrib.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/modules/features/foobar.aas.common.kkkkkkkkkkk.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.common.adapters_11.1.1/foobar.abc.common.adapters.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.plane.adapter_12.1.3/foobar.plane.adapter.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/lib/ccccccccar-common.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/communications/modules/config.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/communications/modules/userprefs-config.jar" + ps + + "/scratch/xxxx/yyyy/XXXXXX/aaaaaaaa/xxxxxxx/xxxxxxxx.us.foobar.com/CommonDomain/config/abc-infra" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/qqqqqq-all-1.6.5.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/foobar.abc.thread.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/thread-rrrrrrr-ext-aas.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.adapter_11.1.1/foobar.abc.adapter.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.ccc_11.1.1/foobar.abc.ccc.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-configuration.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-lang.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/bbb/lib/commons-logging.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.wccore/foobar-ppppppp-api.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/internal/features/rrr_aaxyxx_foobar.rrr.aas.classpath.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.thread_11.1.1/rrrrrrrr-api.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/commons-xxx-1.1.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/abc/abc/modules/foobar.abc.mgmt_11.1.1/abc-infra-mgmt.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/eee/archives/eee-eee.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/marchnet.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/marchclient.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/aaserver/common/march/lib/march.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/jlib/iiiloader.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/xxxxxxyyzzzzz/classes-xxxxxxyyzzzzz.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_core.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_codec.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/wwcontent/cde/iii/components/mmmmmmm/lib/abc_imageio.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/jdk/lib/tools.jar" + ps + + "/scratch/xxxx/yyyy/ZZZZZZ/aaaaaaaaaa/xx/foobar_common/modules/foobar.ooo_12.1.3/ooo-manifest.jar"; + + String myCP = longClassPath + ps + appJar; + // Dump an archive with a specified JAR file in -classpath + TestCommon.testDump(myCP, TestCommon.list("Hello")); + + TestCommon.run( + "-XX:+TraceClassPaths", + "-cp", appJar, + "Hello"); + } +} + diff --git a/hotspot/test/runtime/appcds/WideIloadTest.java b/hotspot/test/runtime/appcds/WideIloadTest.java new file mode 100644 index 00000000..9c045882 --- /dev/null +++ b/hotspot/test/runtime/appcds/WideIloadTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, 2017, 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. + * + */ + +/** + * @test + * @summary Test 'iload_w' bytecode in shared class + * @library /testlibrary + * @compile test-classes/Iloadw.jasm + * @compile test-classes/IloadwMain.java + * @run main WideIloadTest + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class WideIloadTest { + public static void main(String args[]) throws Exception { + JarBuilder.build("iload_w", "Iloadw", "IloadwMain"); + String appJar = TestCommon.getTestJar("iload_w.jar"); + OutputAnalyzer dumpOutput = TestCommon.dump(appJar, TestCommon.list( + "Iloadw", "IloadwMain")); + TestCommon.checkDump(dumpOutput); + OutputAnalyzer execOutput = TestCommon.exec(appJar, "IloadwMain"); + TestCommon.checkExec(execOutput, "Passed"); + } +} diff --git a/hotspot/test/runtime/appcds/XShareAutoWithChangedJar.java b/hotspot/test/runtime/appcds/XShareAutoWithChangedJar.java new file mode 100644 index 00000000..f59f2f89 --- /dev/null +++ b/hotspot/test/runtime/appcds/XShareAutoWithChangedJar.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, 2017, 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. + * + */ + +/* + * @test + * @summary Test -Xshare:auto for AppCDS + * @library /testlibrary + * @compile test-classes/Hello.java + * @run main XShareAutoWithChangedJar + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class XShareAutoWithChangedJar { + public static void main(String[] args) throws Exception { + String appJar = JarBuilder.build("XShareAutoWithChangedJar", "Hello"); + + // 1. dump + OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("Hello")); + TestCommon.checkDump(output); + + // 2. change the jar + JarBuilder.build("XShareAutoWithChangedJar", "Hello"); + + // 3. exec + output = TestCommon.execAuto("-cp", appJar, "Hello"); + output.shouldContain("Hello World"); + } +} + diff --git a/hotspot/test/runtime/appcds/test-classes/C1.java b/hotspot/test/runtime/appcds/test-classes/C1.java new file mode 100644 index 00000000..86201cd4 --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/C1.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, 2017, 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 sealed.pkg; + +public class C1 { +} diff --git a/hotspot/test/runtime/appcds/test-classes/C2.java b/hotspot/test/runtime/appcds/test-classes/C2.java new file mode 100644 index 00000000..ad0026fb --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/C2.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014, 2017, 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 pkg; + +public class C2 { +} diff --git a/hotspot/test/runtime/appcds/test-classes/CheckIfShared.java b/hotspot/test/runtime/appcds/test-classes/CheckIfShared.java new file mode 100644 index 00000000..59b91f48 --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/CheckIfShared.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015, 2017, 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 sun.hotspot.WhiteBox; + +public class CheckIfShared { + public static void main(String args[]) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + if ("true".equals(args[0])) { + if (!wb.isSharedClass(CheckIfShared.class)) { + throw new RuntimeException("wb.isSharedClass(CheckIfShared.class) should be true"); + } + } else { + if (wb.isSharedClass(CheckIfShared.class)) { + throw new RuntimeException("wb.isSharedClass(CheckIfShared.class) should be false"); + } + } + } +} + diff --git a/hotspot/test/runtime/appcds/test-classes/Hello.java b/hotspot/test/runtime/appcds/test-classes/Hello.java new file mode 100644 index 00000000..dc134771 --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/Hello.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class Hello { + public static void main(String args[]) { + System.out.println("Hello World"); + } +} diff --git a/hotspot/test/runtime/appcds/test-classes/HelloMore.java b/hotspot/test/runtime/appcds/test-classes/HelloMore.java new file mode 100644 index 00000000..0d8f335e --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/HelloMore.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class HelloMore { + public static void main(String args[]) { + Hello.main(args); + System.out.println("Hello World ... More"); + } +} diff --git a/hotspot/test/runtime/appcds/test-classes/Iloadw.jasm b/hotspot/test/runtime/appcds/test-classes/Iloadw.jasm new file mode 100644 index 00000000..5c1fffbf --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/Iloadw.jasm @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class Iloadw + version 51: 0 +{ + public static Method run:"()I" + stack 1 locals 400 + { + iconst_0; + istore_w 300; + iinc_w 300,1; + iload_w 300; + ireturn; + } +} diff --git a/hotspot/test/runtime/appcds/test-classes/IloadwMain.java b/hotspot/test/runtime/appcds/test-classes/IloadwMain.java new file mode 100644 index 00000000..7257cce6 --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/IloadwMain.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016, 2017, 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. + * + */ + +public class IloadwMain { + public static void main(String args[]) { + int result = Iloadw.run(); + if (result != 1) { + throw new RuntimeException( + "Failed. Result is " + result + ", expect 1."); + } else { + System.out.println("Passed."); + } + } +} diff --git a/hotspot/test/runtime/appcds/test-classes/MissingSuper.java b/hotspot/test/runtime/appcds/test-classes/MissingSuper.java new file mode 100644 index 00000000..ef47a7cb --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/MissingSuper.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 2017, 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. + * + */ + +public class MissingSuper { + public static void main(String args[]) { + try { + new MissingSuperSub(); + } catch (NoClassDefFoundError e) { + System.out.println("Expected NoClassDefFoundError:"); + e.printStackTrace(System.out); + } + + try { + new MissingSuperImpl(); + } catch (NoClassDefFoundError e) { + System.out.println("Expected NoClassDefFoundError:"); + e.printStackTrace(System.out); + } + } +} + +class MissingSuperSup {} // This class will be deleted from missing_super.jar before dumping + +class MissingSuperSub extends MissingSuperSup {} + +interface MissingSuperIntf {} // This interface will be deleted from missing_super.jar before dumping + +class MissingSuperImpl implements MissingSuperIntf {} diff --git a/hotspot/test/runtime/appcds/test-classes/PackageSealingTest.java b/hotspot/test/runtime/appcds/test-classes/PackageSealingTest.java new file mode 100644 index 00000000..a1e8ea0a --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/PackageSealingTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 2017, 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.Package; + +public class PackageSealingTest { + public static void main(String args[]) { + try { + Class c1 = PackageSealingTest.class.forName("sealed.pkg.C1"); + Class c2 = PackageSealingTest.class.forName("pkg.C2"); + Package p1 = c1.getPackage(); + System.out.println("Package 1: " + p1.toString()); + Package p2 = c2.getPackage(); + System.out.println("Package 2: " + p2.toString()); + + if (!p1.isSealed()) { + System.out.println("Failed: sealed.pkg is not sealed."); + System.exit(0); + } + + if (p2.isSealed()) { + System.out.println("Failed: pkg is sealed."); + System.exit(0); + } + + System.out.println("OK"); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/hotspot/test/runtime/appcds/test-classes/ParallelClasses.java b/hotspot/test/runtime/appcds/test-classes/ParallelClasses.java new file mode 100644 index 00000000..a4d0520f --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/ParallelClasses.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, 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. + * + */ + +class ParallelClass0 {} +class ParallelClass1 {} +class ParallelClass2 {} +class ParallelClass3 {} +class ParallelClass4 {} +class ParallelClass5 {} +class ParallelClass6 {} +class ParallelClass7 {} +class ParallelClass8 {} +class ParallelClass9 {} +class ParallelClass10 {} +class ParallelClass11 {} +class ParallelClass12 {} +class ParallelClass13 {} +class ParallelClass14 {} +class ParallelClass15 {} +class ParallelClass16 {} +class ParallelClass17 {} +class ParallelClass18 {} +class ParallelClass19 {} +class ParallelClass20 {} +class ParallelClass21 {} +class ParallelClass22 {} +class ParallelClass23 {} +class ParallelClass24 {} +class ParallelClass25 {} +class ParallelClass26 {} +class ParallelClass27 {} +class ParallelClass28 {} +class ParallelClass29 {} +class ParallelClass30 {} +class ParallelClass31 {} +class ParallelClass32 {} +class ParallelClass33 {} +class ParallelClass34 {} +class ParallelClass35 {} +class ParallelClass36 {} +class ParallelClass37 {} +class ParallelClass38 {} +class ParallelClass39 {} diff --git a/hotspot/test/runtime/appcds/test-classes/ParallelLoad.java b/hotspot/test/runtime/appcds/test-classes/ParallelLoad.java new file mode 100644 index 00000000..9a6fe550 --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/ParallelLoad.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016, 2017, 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.io.*; +import java.net.*; +import java.lang.reflect.Field; + + +// This test helper is parameterized by: +// - class transformation mode: property "appcds.parallel.transform.mode" +// - class loader test types +// +// In the case of transformMode == "cflh", the transformation is performed +// by AppCDS/jvmti/TransformerAgent.java. The classes to be transformed, such as +// ParallelClassTr0, are defined in ./jvmti/parallelLoad/ParallelClasses.java + +public class ParallelLoad { + public static int MAX_CLASSES = 40; + public static int NUM_THREADS = 4; + + public final static int SYSTEM_LOADER = 0; + public final static int SINGLE_CUSTOM_LOADER = 1; + public final static int MULTI_CUSTOM_LOADER = 2; + + public static final int FINGERPRINT_MODE = 1; + public static final int API_MODE = 2; + + public static int loaderType = SYSTEM_LOADER; + public static ClassLoader classLoaders[]; + public static int mode = FINGERPRINT_MODE; + + public static float timeoutFactor = + Float.parseFloat(System.getProperty("test.timeout.factor", "1.0")); + + public static void main(String args[]) throws Throwable { + run(args, null); + } + public static void run(String args[], ClassLoader loaders[]) throws Throwable { + String customJar = null; + System.out.println("ParallelLoad: timeoutFactor = " + timeoutFactor); + + if (args.length >= 1) { + if ("SINGLE_CUSTOM_LOADER".equals(args[0])) { + loaderType = SINGLE_CUSTOM_LOADER; + customJar = args[2]; + } else if ("MULTI_CUSTOM_LOADER".equals(args[0])) { + loaderType = MULTI_CUSTOM_LOADER; + customJar = args[2]; + } else if ("SYSTEM_LOADER".equals(args[0])) { + loaderType = SYSTEM_LOADER; + } else { + throw new RuntimeException("Unexpected loaderType" + args[0]); + } + } + + if (customJar != null) { + if ("FINGERPRINT_MODE".equals(args[1])) { + mode = FINGERPRINT_MODE; + classLoaders = new ClassLoader[NUM_THREADS]; + for (int i=0; i<NUM_THREADS; i++) { + URL url = new File(customJar).toURI().toURL(); + URL[] urls = new URL[] {url}; + classLoaders[i] = new URLClassLoader(urls); + } + } else { + // Loaders must be supplied by caller of the run() method + mode = API_MODE; + classLoaders = loaders; + } + } + + System.out.println("Start Parallel Load ..."); + + Thread thread[] = new Thread[NUM_THREADS]; + for (int i=0; i<NUM_THREADS; i++) { + Thread t = new ParallelLoadThread(i); + t.start(); + thread[i] = t; + } + + Thread watchdog = new ParallelLoadWatchdog(); + watchdog.setDaemon(true); + watchdog.start(); + + for (int i=0; i<NUM_THREADS; i++) { + thread[i].join(); + } + System.out.println("Parallel Load ... done"); + System.exit(0); + } +} + + +class ParallelLoadWatchdog extends Thread { + public void run() { + try { + long timeout = (long) (20 * 1000 * ParallelLoad.timeoutFactor); + Thread.sleep(timeout); + System.out.println("ParallelLoadWatchdog: Timeout reached: timeout(ms) = " + timeout); + System.exit(1); + } catch (Throwable t) { + t.printStackTrace(); + System.exit(1); + } + } +}; + + +class ParallelLoadThread extends Thread { + static int num_ready[] = new int[ParallelLoad.MAX_CLASSES]; + static Object lock = new Object(); + static String transformMode = + System.getProperty("appcds.parallel.transform.mode", "none"); + + int thread_id; + ParallelLoadThread(int thread_id) { + this.thread_id = thread_id; + } + + public void run() { + try { + run0(); + } catch (Throwable t) { + t.printStackTrace(); + System.exit(1); + } + } + + private static void log(String msg, Object... args) { + String msg0 = "ParallelLoadThread: " + String.format(msg, args); + System.out.println(msg0); + } + + private void run0() throws Throwable { + for (int i=0; i<ParallelLoad.MAX_CLASSES; i++) { + synchronized(lock) { + num_ready[i] ++; + while (num_ready[i] < ParallelLoad.NUM_THREADS) { + lock.wait(); + } + lock.notifyAll(); + } + log("this = %s %d", this, i); + String className = "ParallelClass" + i; + if (transformMode.equals("cflh")) + className = "ParallelClassTr" + i; + + Class clazz = null; + + switch (ParallelLoad.loaderType) { + case ParallelLoad.SYSTEM_LOADER: + clazz = Class.forName(className); + break; + case ParallelLoad.SINGLE_CUSTOM_LOADER: + clazz = ParallelLoad.classLoaders[0].loadClass(className); + break; + case ParallelLoad.MULTI_CUSTOM_LOADER: + clazz = ParallelLoad.classLoaders[thread_id].loadClass(className); + break; + } + + log("clazz = %s", clazz); + testTransformation(clazz); + } + } + + private void testTransformation(Class c) throws Exception { + if (transformMode.equals("none")) + return; + + // currently only cflh transform mode is supported + if (!transformMode.equals("cflh")) { + String msg = "wrong transform mode: " + transformMode; + throw new IllegalArgumentException(msg); + } + + Field[] fields = c.getFields(); + boolean fieldFound = false; + for (Field f : fields) { + if (f.getName().equals("testString")) { + checkTransformationString(c, (String) f.get(null)); + fieldFound = true; + } + } + + if (!fieldFound) + throw new RuntimeException ("Expected field 'testString' not found"); + } + + private void checkTransformationString(Class c, String actual) throws Exception { + String expected = "class-transform-check: this-has-been--transformed"; + if (!actual.equals(expected)) { + String msg1 = "Transformation failed for class" + c.getName(); + String msg2 = String.format("Expected: %s, actual: %s", expected, actual); + throw new RuntimeException(msg1 + "\n" + msg2); + } + } +} + diff --git a/hotspot/test/runtime/appcds/test-classes/package_seal.mf b/hotspot/test/runtime/appcds/test-classes/package_seal.mf new file mode 100644 index 00000000..e34c7ab5 --- /dev/null +++ b/hotspot/test/runtime/appcds/test-classes/package_seal.mf @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Created-By: 1.9.0-internal (Oracle Corporation) + +Name: sealed/pkg/ +Sealed: true diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java index 67806cab..2132325f 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java @@ -164,6 +164,21 @@ public final class OutputAnalyzer { return this; } + /** + * Verify the exit value of the process + * backport from jdk11u + * @param notExpectedExitValue Unexpected exit value from process + * @throws RuntimeException If the exit value from the process did match the expected value + */ + public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) { + if (getExitValue() == notExpectedExitValue) { + reportDiagnosticSummary(); + throw new RuntimeException("Unexpected to get exit value of [" + + notExpectedExitValue + "]\n"); + } + return this; + } + /** * Verify that the stdout and stderr contents of output buffer does not contain the string * diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java index 902e3b13..be48a7e6 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java @@ -395,4 +395,56 @@ public final class Utils { return Files.createTempDirectory(dir, prefix); } + // This method is intended to be called from a jtreg test. + // It will identify the name of the test by means of stack walking. + // It can handle both jtreg tests and a testng tests wrapped inside jtreg tests. + // For jtreg tests the name of the test will be searched by stack-walking + // until the method main() is found; the class containing that method is the + // main test class and will be returned as the name of the test. + // Special handling is used for testng tests. + // backport from jdk11u + public static String getTestName() { + String result = null; + // If we are using testng, then we should be able to load the "Test" annotation. + Class testClassAnnotation; + + try { + testClassAnnotation = Class.forName("org.testng.annotations.Test"); + } catch (ClassNotFoundException e) { + testClassAnnotation = null; + } + + StackTraceElement[] elms = (new Throwable()).getStackTrace(); + for (StackTraceElement n: elms) { + String className = n.getClassName(); + + // If this is a "main" method, then use its class name, but only + // if we are not using testng. + if (testClassAnnotation == null && "main".equals(n.getMethodName())) { + result = className; + break; + } + + // If this is a testng test, the test will have no "main" method. We can + // detect a testng test class by looking for the org.testng.annotations.Test + // annotation. If present, then use the name of this class. + if (testClassAnnotation != null) { + try { + Class c = Class.forName(className); + if (c.isAnnotationPresent(testClassAnnotation)) { + result = className; + break; + } + } catch (ClassNotFoundException e) { + throw new RuntimeException("Unexpected exception: " + e, e); + } + } + } + + if (result == null) { + throw new RuntimeException("Couldn't find main test class in stack trace"); + } + + return result; + } } diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cds/CDSOptions.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cds/CDSOptions.java new file mode 100644 index 00000000..09050d6c --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cds/CDSOptions.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, 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 com.oracle.java.testlibrary.cds; + +import java.util.ArrayList; + +// This class represents options used +// during creation of CDS archive and/or running JVM with a CDS archive +public class CDSOptions { + public String xShareMode = "on"; + public String archiveName; + public ArrayList<String> prefix = new ArrayList<String>(); + public ArrayList<String> suffix = new ArrayList<String>(); + + // Indicate whether to append "-version" when using CDS Archive. + // Most of tests will use '-version' + public boolean useVersion = true; + + + public CDSOptions() { + } + + + public CDSOptions addPrefix(String... prefix) { + for (String s : prefix) this.prefix.add(s); + return this; + } + + + public CDSOptions addSuffix(String... suffix) { + for (String s : suffix) this.suffix.add(s); + return this; + } + + public CDSOptions setXShareMode(String mode) { + this.xShareMode = mode; + return this; + } + + + public CDSOptions setArchiveName(String name) { + this.archiveName = name; + return this; + } + + + public CDSOptions setUseVersion(boolean use) { + this.useVersion = use; + return this; + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cds/CDSTestUtils.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cds/CDSTestUtils.java new file mode 100644 index 00000000..f1ff7e48 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cds/CDSTestUtils.java @@ -0,0 +1,590 @@ +/* + * Copyright (c) 2017, 2018, 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 com.oracle.java.testlibrary.cds; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.Utils; + + +// This class contains common test utilities for testing CDS +public class CDSTestUtils { + public static final String MSG_RANGE_NOT_WITHIN_HEAP = + "UseSharedSpaces: Unable to allocate region, range is not within java heap."; + public static final String MSG_RANGE_ALREADT_IN_USE = + "Unable to allocate region, java heap range is already in use."; + public static final String MSG_COMPRESSION_MUST_BE_USED = + "Unable to use shared archive: UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces."; + + public interface Checker { + public void check(OutputAnalyzer output) throws Exception; + } + + /* + * INTRODUCTION + * + * When testing various CDS functionalities, we need to launch JVM processes + * using a "launch method" (such as TestCommon.run), and analyze the results of these + * processes. + * + * While typical jtreg tests would use OutputAnalyzer in such cases, due to the + * complexity of CDS failure modes, we have added the CDSTestUtils.Result class + * to make the analysis more convenient and less error prone. + * + * A Java process can end in one of the following 4 states: + * + * 1: Unexpected error - such as JVM crashing. In this case, the "launch method" + * will throw a RuntimeException. + * 2: Mapping Failure - this happens when the OS (intermittently) fails to map the + * CDS archive, normally caused by Address Space Layout Randomization. + * We usually treat this as "pass". + * 3: Normal Exit - the JVM process has finished without crashing, and the exit code is 0. + * 4: Abnormal Exit - the JVM process has finished without crashing, and the exit code is not 0. + * + * In most test cases, we need to check the JVM process's output in cases 3 and 4. However, we need + * to make sure that our test code is not confused by case 2. + * + * For example, a JVM process is expected to print the string "Hi" and exit with 0. With the old + * CDSTestUtils.runWithArchive API, the test may be written as this: + * + * OutputAnalyzer out = CDSTestUtils.runWithArchive(args); + * out.shouldContain("Hi"); + * + * However, if the JVM process fails with mapping failure, the string "Hi" will not be in the output, + * and your test case will fail intermittently. + * + * Instead, the test case should be written as + * + * CCDSTestUtils.run(args).assertNormalExit("Hi"); + * + * EXAMPLES/HOWTO + * + * 1. For simple substring matching: + * + * CCDSTestUtils.run(args).assertNormalExit("Hi"); + * CCDSTestUtils.run(args).assertNormalExit("a", "b", "x"); + * CCDSTestUtils.run(args).assertAbnormalExit("failure 1", "failure2"); + * + * 2. For more complex output matching: using Lambda expressions + * + * CCDSTestUtils.run(args) + * .assertNormalExit(output -> output.shouldNotContain("this should not be printed"); + * CCDSTestUtils.run(args) + * .assertAbnormalExit(output -> { + * output.shouldNotContain("this should not be printed"); + * output.shouldHaveExitValue(123); + * }); + * + * 3. Chaining several checks: + * + * CCDSTestUtils.run(args) + * .assertNormalExit(output -> output.shouldNotContain("this should not be printed") + * .assertNormalExit("should have this", "should have that"); + * + * 4. [Rare use case] if a test sometimes exit normally, and sometimes abnormally: + * + * CCDSTestUtils.run(args) + * .ifNormalExit("ths string is printed when exiting with 0") + * .ifAbNormalExit("ths string is printed when exiting with 1"); + * + * NOTE: you usually don't want to write your test case like this -- it should always + * exit with the same exit code. (But I kept this API because some existing test cases + * behave this way -- need to revisit). + */ + public static class Result { + private final OutputAnalyzer output; + private final CDSOptions options; + private final boolean hasMappingFailure; + private final boolean hasAbnormalExit; + private final boolean hasNormalExit; + private final String CDS_DISABLED = "warning: CDS is disabled when the"; + + public Result(CDSOptions opts, OutputAnalyzer out) throws Exception { + options = opts; + output = out; + hasMappingFailure = CDSTestUtils.checkCommonExecExceptions(output); + hasAbnormalExit = (!hasMappingFailure) && (output.getExitValue() != 0); + hasNormalExit = (!hasMappingFailure) && (output.getExitValue() == 0); + + if (hasNormalExit) { + if ("on".equals(options.xShareMode) && + output.getStderr().contains("java version") && + !output.getStderr().contains(CDS_DISABLED)) { + // "-showversion" is always passed in the command-line by the execXXX methods. + // During normal exit, we require that the VM to show that sharing was enabled. + output.shouldContain("sharing"); + } + } + } + + public Result assertNormalExit(Checker checker) throws Exception { + if (!hasMappingFailure) { + checker.check(output); + output.shouldHaveExitValue(0); + } + return this; + } + + public Result assertAbnormalExit(Checker checker) throws Exception { + if (!hasMappingFailure) { + checker.check(output); + output.shouldNotHaveExitValue(0); + } + return this; + } + + // When {--limit-modules, --patch-module, and/or --upgrade-module-path} + // are specified, CDS is silently disabled for both -Xshare:auto and -Xshare:on. + public Result assertSilentlyDisabledCDS(Checker checker) throws Exception { + if (hasMappingFailure) { + throw new RuntimeException("Unexpected mapping failure"); + } + // this comes from a JVM warning message. + output.shouldContain(CDS_DISABLED); + + checker.check(output); + return this; + } + + public Result assertSilentlyDisabledCDS(int exitCode, String... matches) throws Exception { + return assertSilentlyDisabledCDS((out) -> { + out.shouldHaveExitValue(exitCode); + checkMatches(out, matches); + }); + } + + public Result ifNormalExit(Checker checker) throws Exception { + if (hasNormalExit) { + checker.check(output); + } + return this; + } + + public Result ifAbnormalExit(Checker checker) throws Exception { + if (hasAbnormalExit) { + checker.check(output); + } + return this; + } + + public Result ifNoMappingFailure(Checker checker) throws Exception { + if (!hasMappingFailure) { + checker.check(output); + } + return this; + } + + + public Result assertNormalExit(String... matches) throws Exception { + if (!hasMappingFailure) { + checkMatches(output, matches); + output.shouldHaveExitValue(0); + } + return this; + } + + public Result assertAbnormalExit(String... matches) throws Exception { + if (!hasMappingFailure) { + checkMatches(output, matches); + output.shouldNotHaveExitValue(0); + } + + return this; + } + } + + // Specify this property to copy sdandard output of the child test process to + // the parent/main stdout of the test. + // By default such output is logged into a file, and is copied into the main stdout. + public static final boolean CopyChildStdoutToMainStdout = + Boolean.valueOf(System.getProperty("test.cds.copy.child.stdout", "true")); + + // This property is passed to child test processes + public static final String TestTimeoutFactor = System.getProperty("test.timeout.factor", "1.0"); + + public static final String UnableToMapMsg = + "Unable to map shared archive: test did not complete; assumed PASS"; + + // Create bootstrap CDS archive, + // use extra JVM command line args as a prefix. + // For CDS tests specifying prefix makes more sense than specifying suffix, since + // normally there are no classes or arguments to classes, just "-version" + // To specify suffix explicitly use CDSOptions.addSuffix() + public static OutputAnalyzer createArchive(String... cliPrefix) + throws Exception { + return createArchive((new CDSOptions()).addPrefix(cliPrefix)); + } + + // Create bootstrap CDS archive + public static OutputAnalyzer createArchive(CDSOptions opts) + throws Exception { + + startNewArchiveName(); + + ArrayList<String> cmd = new ArrayList<String>(); + + for (String p : opts.prefix) cmd.add(p); + + cmd.add("-Xshare:dump"); + cmd.add("-Xlog:cds,cds+hashtables"); + if (opts.archiveName == null) + opts.archiveName = getDefaultArchiveName(); + cmd.add("-XX:SharedArchiveFile=./" + opts.archiveName); + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + return executeAndLog(pb, "dump"); + } + + + // check result of 'dump-the-archive' operation, that is "-Xshare:dump" + public static OutputAnalyzer checkDump(OutputAnalyzer output, String... extraMatches) + throws Exception { + + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + + for (String match : extraMatches) { + output.shouldContain(match); + } + + return output; + } + + + // A commonly used convenience methods to create an archive and check the results + // Creates an archive and checks for errors + public static OutputAnalyzer createArchiveAndCheck(CDSOptions opts) + throws Exception { + return checkDump(createArchive(opts)); + } + + + public static OutputAnalyzer createArchiveAndCheck(String... cliPrefix) + throws Exception { + return checkDump(createArchive(cliPrefix)); + } + + + // This method should be used to check the output of child VM for common exceptions. + // Most of CDS tests deal with child VM processes for creating and using the archive. + // However exceptions that occur in the child process do not automatically propagate + // to the parent process. This mechanism aims to improve the propagation + // of exceptions and common errors. + // Exception e argument - an exception to be re-thrown if none of the common + // exceptions match. Pass null if you wish not to re-throw any exception. + public static boolean checkCommonExecExceptions(OutputAnalyzer output, Exception e) + throws Exception { + if (output.getStdout().contains("https://bugreport.java.com/bugreport/crash.jsp")) { + throw new RuntimeException("Hotspot crashed"); + } + if (output.getStdout().contains("TEST FAILED")) { + throw new RuntimeException("Test Failed"); + } + if (output.getOutput().contains("Unable to unmap shared space")) { + throw new RuntimeException("Unable to unmap shared space"); + } + + // Special case -- sometimes Xshare:on fails because it failed to map + // at given address. This behavior is platform-specific, machine config-specific + // and can be random (see ASLR). + if (isUnableToMap(output)) { + System.out.println(UnableToMapMsg); + return true; + } + + if (e != null) { + throw e; + } + return false; + } + + public static boolean checkCommonExecExceptions(OutputAnalyzer output) throws Exception { + return checkCommonExecExceptions(output, null); + } + + + // Check the output for indication that mapping of the archive failed. + // Performance note: this check seems to be rather costly - searching the entire + // output stream of a child process for multiple strings. However, it is necessary + // to detect this condition, a failure to map an archive, since this is not a real + // failure of the test or VM operation, and results in a test being "skipped". + // Suggestions to improve: + // 1. VM can designate a special exit code for such condition. + // 2. VM can print a single distinct string indicating failure to map an archive, + // instead of utilizing multiple messages. + // These are suggestions to improve testibility of the VM. However, implementing them + // could also improve usability in the field. + public static boolean isUnableToMap(OutputAnalyzer output) { + String outStr = output.getOutput(); + if ((output.getExitValue() == 1) && ( + outStr.contains("Unable to reserve shared space at required address") || + outStr.contains("Unable to map ReadOnly shared space at required address") || + outStr.contains("Unable to map ReadWrite shared space at required address") || + outStr.contains("Unable to map MiscData shared space at required address") || + outStr.contains("Unable to map MiscCode shared space at required address") || + outStr.contains("Unable to map OptionalData shared space at required address") || + outStr.contains("Could not allocate metaspace at a compatible address") || + outStr.contains("UseSharedSpaces: Unable to allocate region, range is not within java heap") )) + { + return true; + } + + return false; + } + + public static Result run(String... cliPrefix) throws Exception { + CDSOptions opts = new CDSOptions(); + opts.setArchiveName(getDefaultArchiveName()); + opts.addPrefix(cliPrefix); + return new Result(opts, runWithArchive(opts)); + } + + public static Result run(CDSOptions opts) throws Exception { + return new Result(opts, runWithArchive(opts)); + } + + // Execute JVM with CDS archive, specify command line args suffix + public static OutputAnalyzer runWithArchive(String... cliPrefix) + throws Exception { + + return runWithArchive( (new CDSOptions()) + .setArchiveName(getDefaultArchiveName()) + .addPrefix(cliPrefix) ); + } + + + // Execute JVM with CDS archive, specify CDSOptions + public static OutputAnalyzer runWithArchive(CDSOptions opts) + throws Exception { + + ArrayList<String> cmd = new ArrayList<String>(); + + for (String p : opts.prefix) cmd.add(p); + + cmd.add("-Xshare:" + opts.xShareMode); + cmd.add("-Dtest.timeout.factor=" + TestTimeoutFactor); + + if (opts.archiveName == null) + opts.archiveName = getDefaultArchiveName(); + cmd.add("-XX:SharedArchiveFile=" + opts.archiveName); + + if (opts.useVersion) + cmd.add("-version"); + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + return executeAndLog(pb, "exec"); + } + + + // A commonly used convenience methods to create an archive and check the results + // Creates an archive and checks for errors + public static OutputAnalyzer runWithArchiveAndCheck(CDSOptions opts) throws Exception { + return checkExec(runWithArchive(opts)); + } + + + public static OutputAnalyzer runWithArchiveAndCheck(String... cliPrefix) throws Exception { + return checkExec(runWithArchive(cliPrefix)); + } + + + public static OutputAnalyzer checkExec(OutputAnalyzer output, + String... extraMatches) throws Exception { + CDSOptions opts = new CDSOptions(); + return checkExec(output, opts, extraMatches); + } + + + // check result of 'exec' operation, that is when JVM is run using the archive + public static OutputAnalyzer checkExec(OutputAnalyzer output, CDSOptions opts, + String... extraMatches) throws Exception { + try { + if ("on".equals(opts.xShareMode)) { + output.shouldContain("sharing"); + } + output.shouldHaveExitValue(0); + } catch (RuntimeException e) { + checkCommonExecExceptions(output, e); + return output; + } + + checkMatches(output, extraMatches); + return output; + } + + + public static OutputAnalyzer checkExecExpectError(OutputAnalyzer output, + int expectedExitValue, + String... extraMatches) throws Exception { + if (isUnableToMap(output)) { + System.out.println(UnableToMapMsg); + return output; + } + + output.shouldHaveExitValue(expectedExitValue); + checkMatches(output, extraMatches); + return output; + } + + public static OutputAnalyzer checkMatches(OutputAnalyzer output, + String... matches) throws Exception { + for (String match : matches) { + output.shouldContain(match); + } + return output; + } + + + // get the file object for the test artifact + public static File getTestArtifact(String name, boolean checkExistence) { + File dir = new File(System.getProperty("test.classes", ".")); + File file = new File(dir, name); + + if (checkExistence && !file.exists()) { + throw new RuntimeException("Cannot find " + file.getPath()); + } + + return file; + } + + + // create file containing the specified class list + public static File makeClassList(String classes[]) + throws Exception { + return makeClassList(getTestName() + "-", classes); + } + + // create file containing the specified class list + public static File makeClassList(String testCaseName, String classes[]) + throws Exception { + + File classList = getTestArtifact(testCaseName + "test.classlist", false); + FileOutputStream fos = new FileOutputStream(classList); + PrintStream ps = new PrintStream(fos); + + addToClassList(ps, classes); + + ps.close(); + fos.close(); + + return classList; + } + + + public static void addToClassList(PrintStream ps, String classes[]) + throws IOException + { + if (classes != null) { + for (String s : classes) { + ps.println(s); + } + } + } + + + // Optimization for getting a test name. + // Test name does not change during execution of the test, + // but getTestName() uses stack walking hence it is expensive. + // Therefore cache it and reuse it. + private static String testName; + public static String getTestName() { + if (testName == null) { + testName = Utils.getTestName(); + } + return testName; + } + + private static final SimpleDateFormat timeStampFormat = + new SimpleDateFormat("HH'h'mm'm'ss's'SSS"); + + private static String defaultArchiveName; + + // Call this method to start new archive with new unique name + public static void startNewArchiveName() { + defaultArchiveName = getTestName() + + timeStampFormat.format(new Date()) + ".jsa"; + } + + public static String getDefaultArchiveName() { + return defaultArchiveName; + } + + + // ===================== FILE ACCESS convenience methods + public static File getOutputFile(String name) { + File dir = new File(System.getProperty("test.classes", ".")); + return new File(dir, getTestName() + "-" + name); + } + + + public static File getOutputSourceFile(String name) { + File dir = new File(System.getProperty("test.classes", ".")); + return new File(dir, name); + } + + + public static File getSourceFile(String name) { + File dir = new File(System.getProperty("test.src", ".")); + return new File(dir, name); + } + + + // ============================= Logging + public static OutputAnalyzer executeAndLog(ProcessBuilder pb, String logName) throws Exception { + long started = System.currentTimeMillis(); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + writeFile(getOutputFile(logName + ".stdout"), output.getStdout()); + writeFile(getOutputFile(logName + ".stderr"), output.getStderr()); + System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]"); + System.out.println("[STDERR]\n" + output.getStderr()); + + if (CopyChildStdoutToMainStdout) + System.out.println("[STDOUT]\n" + output.getStdout()); + + return output; + } + + + private static void writeFile(File file, String content) throws Exception { + FileOutputStream fos = new FileOutputStream(file); + PrintStream ps = new PrintStream(fos); + ps.print(content); + ps.close(); + fos.close(); + } +} diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/compiler/CompilerUtils.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/compiler/CompilerUtils.java new file mode 100644 index 00000000..a02a1742 --- /dev/null +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/compiler/CompilerUtils.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, 2018, 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 com.oracle.java.testlibrary.compiler; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +/** + * This class consists exclusively of static utility methods for invoking the + * java compiler. + */ +public final class CompilerUtils { + private CompilerUtils() { + } + + /** + * Compile all the java sources in {@code <source>/**} to + * {@code <destination>/**}. The destination directory will be created if + * it doesn't exist. + * <p> + * Equivalent to calling {@code compile(source, destination, true, options);}. + * <p> + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @param source Path to the source directory + * @param destination Path to the destination directory + * @param options Any options to pass to the compiler + * @return true if the compilation is successful + * @throws IOException if there is an I/O error scanning the source tree or + * creating the destination directory + * @throws UnsupportedOperationException if there is no system java compiler + */ + public static boolean compile(Path source, Path destination, String... options) + throws IOException { + return compile(source, destination, true, options); + } + + /** + * Compile all the java sources in {@code <source>} and optionally its + * subdirectories, to + * {@code <destination>}. The destination directory will be created if + * it doesn't exist. + * <p> + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @param source Path to the source directory + * @param destination Path to the destination directory + * @param recurse If {@code true} recurse into any {@code source} subdirectories + * to compile all java source files; else only compile those directly in + * {@code source}. + * @param options Any options to pass to the compiler + * @return true if the compilation is successful + * @throws IOException if there is an I/O error scanning the source tree or + * creating the destination directory + * @throws UnsupportedOperationException if there is no system java compiler + */ + + public static boolean compile(Path source, Path destination, boolean recurse, String... options) + throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + // no compiler available + throw new UnsupportedOperationException("Unable to get system java compiler. " + + "Perhaps, jdk.compiler module is not available."); + } + StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); + + List<File> sources + = Files.find(source, (recurse ? Integer.MAX_VALUE : 1), + (file, attrs) -> (file.toString().endsWith(".java"))) + .map(e -> e.toFile()) // use jdk1.8 + .collect(Collectors.toList()); + + Files.createDirectories(destination); +// jfm.setLocation(StandardLocation.CLASS_PATH, Collections.emptyList()); comment out , use jdk1.8, backport from jdk11u + jfm.setLocation(StandardLocation.CLASS_OUTPUT, + Collections.singletonList(destination.toFile())); + + List<String> opts = Arrays.asList(options); + JavaCompiler.CompilationTask task + = compiler.getTask(null, jfm, null, opts, null, + jfm.getJavaFileObjectsFromFiles(sources)); // use jdk1.8 + + return task.call(); + } +} diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java index 909e09f9..f06b1cbb 100644 --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java @@ -28,9 +28,11 @@ import java.lang.management.MemoryUsage; import java.lang.reflect.Executable; import java.util.Arrays; import java.util.List; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; import java.security.BasicPermission; +import java.util.Objects; import java.net.URL; import sun.hotspot.parser.DiagnosticCommand; @@ -140,6 +142,31 @@ public class WhiteBox { } public native boolean isMethodCompilable(Executable method, int compLevel, boolean isOsr); public native boolean isMethodQueuedForCompilation(Executable method); + + // Determine if the compiler corresponding to the compilation level 'compLevel' + // and to the compilation context 'compilation_context' provides an intrinsic + // for the method 'method'. An intrinsic is available for method 'method' if: + // - the intrinsic is enabled (by using the appropriate command-line flag) and + // - the platform on which the VM is running provides the instructions necessary + // for the compiler to generate the intrinsic code. + // + // The compilation context is related to using the DisableIntrinsic flag on a + // per-method level, see hotspot/src/share/vm/compiler/abstractCompiler.hpp + // for more details. + public boolean isIntrinsicAvailable(Executable method, + Executable compilationContext, + int compLevel) { + Objects.requireNonNull(method); + return isIntrinsicAvailable0(method, compilationContext, compLevel); + } + // If usage of the DisableIntrinsic flag is not expected (or the usage can be ignored), + // use the below method that does not require the compilation context as argument. + public boolean isIntrinsicAvailable(Executable method, int compLevel) { + return isIntrinsicAvailable(method, null, compLevel); + } + private native boolean isIntrinsicAvailable0(Executable method, + Executable compilationContext, + int compLevel); public int deoptimizeMethod(Executable method) { return deoptimizeMethod(method, false /*not osr*/); } diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/code/Compiler.java b/hotspot/test/testlibrary/whitebox/sun/hotspot/code/Compiler.java new file mode 100644 index 00000000..bb06f1af --- /dev/null +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/code/Compiler.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018, 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.hotspot.code; + +import java.lang.reflect.Executable; +import sun.hotspot.WhiteBox; + +/** + * API to obtain information about enabled JIT compilers + * retrieved from the VM with the WhiteBox API. + */ +public class Compiler { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + /** + * Check if Graal is used as JIT compiler. + * + * Graal is enabled if following conditions are true: + * - we are not in Interpreter mode + * - UseJVMCICompiler flag is true + * - jvmci.Compiler variable is equal to 'graal' + * - TieredCompilation is not used or TieredStopAtLevel is greater than 3 + * No need to check client mode because it set UseJVMCICompiler to false. + * + * @return true if Graal is used as JIT compiler. + */ + public static boolean isGraalEnabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean useJvmciComp = WB.getBooleanVMFlag("UseJVMCICompiler"); + if (useJvmciComp == null || !useJvmciComp) { + return false; + } + // This check might be redundant but let's keep it for now. + String jvmciCompiler = System.getProperty("jvmci.Compiler"); + if (jvmciCompiler == null || !jvmciCompiler.equals("graal")) { + return false; + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel"); + // if TieredCompilation is enabled and compilation level is <= 3 then no Graal is used + if (tieredCompilation != null && tieredCompilation && + compLevel != null && compLevel <= 3) { + return false; + } + return true; + } + + /** + * Check if C2 is used as JIT compiler. + * + * C2 is enabled if following conditions are true: + * - we are not in Interpreter mode + * - we are in Server compilation mode + * - TieredCompilation is not used or TieredStopAtLevel is greater than 3 + * - Graal is not used + * + * @return true if C2 is used as JIT compiler. + */ + public static boolean isC2Enabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean serverMode = WB.getBooleanVMFlag("ProfileInterpreter"); + if (serverMode == null || !serverMode) { + return false; + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel"); + // if TieredCompilation is enabled and compilation level is <= 3 then no Graal is used + if (tieredCompilation != null && tieredCompilation && + compLevel != null && compLevel <= 3) { + return false; + } + + if (isGraalEnabled()) { + return false; + } + + return true; + } + + /* + * Check if C1 is used as JIT compiler. + * + * C1 is enabled if following conditions are true: + * - we are not in Interpreter mode + * - we are not in Server compilation mode + * - TieredCompilation is used in Server mode + * + * @return true if C1 is used as JIT compiler. + */ + public static boolean isC1Enabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean serverMode = WB.getBooleanVMFlag("ProfileInterpreter"); + if (serverMode == null || !serverMode) { + return true; // Client mode + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + // C1 is not used in server mode if TieredCompilation is off. + if (tieredCompilation != null && !tieredCompilation) { + return false; + } + return true; + } + + /* + * Determine if the compiler corresponding to the compilation level 'compLevel' + * provides an intrinsic for 'class'.'method'. + */ + public static boolean isIntrinsicAvailable(int compLevel, String klass, String method, Class<?>... parameterTypes) { + Executable intrinsicMethod; + try { + intrinsicMethod = Class.forName(klass).getDeclaredMethod(method, parameterTypes); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Test bug, '" + method + "' method unavailable. " + e); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Test bug, '" + klass + "' class unavailable. " + e); + } + return WB.isIntrinsicAvailable(intrinsicMethod, compLevel); + } +} +
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2