--- a/hotspot/test/gc/TestVerifyDuringStartup.java Thu Sep 05 10:39:10 2013 +0200
+++ b/hotspot/test/gc/TestVerifyDuringStartup.java Mon Sep 09 19:53:28 2013 +0200
@@ -48,7 +48,7 @@
"-XX:+VerifyDuringStartup",
"-version"});
- System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java"));
+ System.out.print("Testing:\n" + JDKToolFinder.getCurrentJDKTool("java"));
for (int i = 0; i < vmOpts.size(); i += 1) {
System.out.print(" " + vmOpts.get(i));
}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java Thu Sep 05 10:39:10 2013 +0200
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java Mon Sep 09 19:53:28 2013 +0200
@@ -27,24 +27,43 @@
public final class JDKToolFinder {
- private JDKToolFinder() {
- }
-
- /**
- * Returns the full path to an executable in jdk/bin based on System property
- * test.jdk (set by jtreg test suite)
- *
- * @return Full path to an executable in jdk/bin
- */
- public static String getJDKTool(String tool) {
- String binPath = System.getProperty("test.jdk");
- if (binPath == null) {
- throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. "
- + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'.");
+ private JDKToolFinder() {
}
- binPath += File.separatorChar + "bin" + File.separatorChar + tool;
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code compile.jdk} (set by jtreg test suite)
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getJDKTool(String tool) {
+ String binPath = System.getProperty("compile.jdk");
+ if (binPath == null) {
+ throw new RuntimeException("System property 'compile.jdk' not set. "
+ + "This property is normally set by jtreg. "
+ + "When running test separately, set this property using "
+ + "'-Dcompile.jdk=/path/to/jdk'.");
+ }
+ binPath += File.separatorChar + "bin" + File.separatorChar + tool;
- return binPath;
- }
+ return binPath;
+ }
+ /**
+ * Returns the full path to an executable in <current jdk>/bin based
+ * on System property {@code test.jdk} (set by jtreg test suite)
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getCurrentJDKTool(String tool) {
+ String binPath = System.getProperty("test.jdk");
+ if (binPath == null) {
+ throw new RuntimeException("System property 'test.jdk' not set. "
+ + "This property is normally set by jtreg. "
+ + "When running test separately, set this property using "
+ + "'-Dtest.jdk=/path/to/jdk'.");
+ }
+ binPath += File.separatorChar + "bin" + File.separatorChar + tool;
+
+ return binPath;
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/Makefile Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,73 @@
+#
+# Copyright (c) 2013, 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.
+#
+#
+
+ifneq "x$(ALT_BOOTDIR)" "x"
+ BOOTDIR := $(ALT_BOOTDIR)
+endif
+
+ifeq "x$(BOOTDIR)" "x"
+ JDK_HOME := $(shell dirname $(shell which java))/..
+else
+ JDK_HOME := $(BOOTDIR)
+endif
+
+SRC_DIR = src
+BUILD_DIR = build
+OUTPUT_DIR = $(BUILD_DIR)/classes
+WHITEBOX_DIR = ../whitebox
+
+JAVAC = $(JDK_HOME)/bin/javac
+JAR = $(JDK_HOME)/bin/jar
+
+SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
+
+MAIN_CLASS = sun.hotspot.tools.ctw.CompileTheWorld
+
+.PHONY: clean cleantmp
+
+all: ctw.jar cleantmp
+
+clean: cleantmp
+ @rm -rf ctw.jar wb.jar
+
+cleantmp:
+ @rm -rf filelist manifest.mf
+ @rm -rf $(BUILD_DIR)
+
+ctw.jar: filelist wb.jar manifest.mf
+ @mkdir -p $(OUTPUT_DIR)
+ $(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp wb.jar @filelist
+ $(JAR) cfm ctw.jar manifest.mf -C $(OUTPUT_DIR) .
+
+wb.jar:
+ make -C ${WHITEBOX_DIR} wb.jar
+ cp ${WHITEBOX_DIR}/wb.jar ./
+ make -C ${WHITEBOX_DIR} clean
+
+filelist: $(SRC_FILES)
+ @rm -f $@
+ @echo $(SRC_FILES) > $@
+
+manifest.mf:
+ @echo "Main-Class: ${MAIN_CLASS}" > manifest.mf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/README Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,93 @@
+#
+# Copyright (c) 2013, 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.
+#
+#
+
+DESCRIPTION
+
+This is replacement for CompileTheWorld (CTW) written on java. Its purpose is
+to make possible the use of CTW in product builds.
+
+DEPENDENCES
+
+The tool depends on Whitebox API. Assumed, that the sources of whitebox are
+located in '../whitebox' directory.
+
+BUILDING
+
+Simple way to build, just type 'make'.
+
+Makefile uses environment variables 'ALT_BOOTDIR', 'BOOTDIR' as root-dir of jdk
+that will be used for compilation and creating jar.
+
+On successful building 'ctw.jar' will be created.
+
+RUNNING
+
+Since the tool uses WhiteBox API, options 'UnlockDiagnosticVMOptions' and
+'WhiteBoxAPI' should be specified, and 'wb.jar' should be added to
+boot-classpath:
+ $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar
+
+Arguments can be paths to '.jar, '.zip', '.lst' files or directories with
+classes, that define which classes will be compiled:
+ - '.jar', '.zip' files and directories are interpreted like in classpath
+(including '<dir>/*' syntax)
+ - '.lst' files -- files with class names (in java notation) to compile.
+CTW will try to find these classes with default class loader, so they should
+be located in classpath.
+
+Without arguments it would work as old version of CTW: all classes in
+boot-classpath will be compiled, excluding classes in 'rt.jar' if 'rt.jar' isn't
+first in boot-classpath.
+
+Due CTW's flags also are not available in product builds, the tool uses
+properties with the same names:
+ - 'CompileTheWorldPreloadClasses' -- type:boolean, default:true, description:
+Preload all classes used by a class before start loading
+ - 'CompileTheWorldStartAt' -- type:long, default:1, description: First class
+to consider
+ - 'CompileTheWorldStopAt' -- type:long, default:Long.MAX_VALUE, description:
+Last class to consider
+
+Also it uses additional properties:
+ - 'sun.hotspot.tools.ctw.verbose' -- type:boolean, default:false,
+description: Verbose output, adds additional information about compilation
+ - 'sun.hotspot.tools.ctw.logfile' -- type:string, default:null,
+description: Path to logfile, if it's null, cout will be used.
+
+EXAMPLES
+
+compile classes from 'rt.jar':
+ $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ${JAVA_HOME}/jre/lib/rt.jar
+
+compile classes from all '.jar' in './testjars' directory:
+ $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./testjars/*
+
+compile classes from './build/classes' directory:
+ $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./build/classes
+
+compile only java.lang.String, java.lang.Object classes:
+ $ echo java.lang.String > classes.lst
+ $ echo java.lang.Object >> classes.lst
+ $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar classes.lst
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.concurrent.Executor;
+
+import java.io.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+
+/**
+ * * Handler for dirs containing classes to compile.
+ * @author igor.ignatyev@oracle.com
+ */
+public class ClassPathDirEntry extends PathHandler {
+
+ private final int rootLength = root.toString().length();
+
+ public ClassPathDirEntry(Path root, Executor executor) {
+ super(root, executor);
+ try {
+ URL url = root.toUri().toURL();
+ setLoader(new URLClassLoader(new URL[]{url}));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void process() {
+ System.out.println("# dir: " + root);
+ if (!Files.exists(root)) {
+ return;
+ }
+ try {
+ Files.walkFileTree(root, EnumSet.of(FileVisitOption.FOLLOW_LINKS),
+ Integer.MAX_VALUE, new CompileFileVisitor());
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+
+ private void processFile(Path file) {
+ if (Utils.isClassFile(file.toString())) {
+ processClass(pathToClassName(file));
+ }
+ }
+
+ private String pathToClassName(Path file) {
+ String fileString;
+ if (root == file) {
+ fileString = file.normalize().toString();
+ } else {
+ fileString = file.normalize().toString().substring(rootLength + 1);
+ }
+ return Utils.fileNameToClassName(fileString);
+ }
+
+ private class CompileFileVisitor extends SimpleFileVisitor<Path> {
+
+ private final Set<Path> ready = new HashSet<>();
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir,
+ BasicFileAttributes attrs) throws IOException {
+ if (ready.contains(dir)) {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ ready.add(dir);
+ return super.preVisitDirectory(dir, attrs);
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file,
+ BasicFileAttributes attrs) throws IOException {
+ if (!ready.contains(file)) {
+ processFile(file);
+ }
+ return isFinished() ? FileVisitResult.TERMINATE
+ : FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file,
+ IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.*;
+import java.util.jar.*;
+import java.util.concurrent.Executor;
+
+import java.io.*;
+import java.nio.file.*;
+
+/**
+ * Handler for jar-files containing classes to compile.
+ * @author igor.ignatyev@oracle.com
+ */
+public class ClassPathJarEntry extends PathHandler {
+
+ public ClassPathJarEntry(Path root, Executor executor) {
+ super(root, executor);
+ try {
+ URL url = root.toUri().toURL();
+ setLoader(new URLClassLoader(new URL[]{url}));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void process() {
+ System.out.println("# jar: " + root);
+ if (!Files.exists(root)) {
+ return;
+ }
+ try {
+ JarFile jarFile = new JarFile(root.toFile());
+ JarEntry entry;
+ for (Enumeration<JarEntry> e = jarFile.entries();
+ e.hasMoreElements(); ) {
+ entry = e.nextElement();
+ processJarEntry(entry);
+ if (isFinished()) {
+ return;
+ }
+ }
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+
+ private void processJarEntry(JarEntry entry) {
+ String filename = entry.getName();
+ if (Utils.isClassFile(filename)) {
+ processClass(Utils.fileNameToClassName(filename));
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.Executor;
+
+/**
+ * Handler for dirs containing jar-files with classes to compile.
+ *
+ * @author igor.ignatyev@oracle.com
+ */
+public class ClassPathJarInDirEntry extends PathHandler {
+
+ public ClassPathJarInDirEntry(Path root, Executor executor) {
+ super(root, executor);
+ }
+
+ @Override
+ public void process() {
+ System.out.println("# jar_in_dir: " + root);
+ if (!Files.exists(root)) {
+ return;
+ }
+ try (DirectoryStream<Path> ds
+ = Files.newDirectoryStream(root, "*.jar")) {
+ for (Path p : ds) {
+ new ClassPathJarEntry(p, executor).process();
+ if (isFinished()) {
+ return;
+ }
+ }
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.Executor;
+
+/**
+ * Handler for files containing a list of classes to compile.
+ *
+ * @author igor.ignatyev@oracle.com
+ */
+public class ClassesListInFile extends PathHandler {
+ public ClassesListInFile(Path root, Executor executor) {
+ super(root, executor);
+ }
+
+ @Override
+ public void process() {
+ System.out.println("# list: " + root);
+ if (!Files.exists(root)) {
+ return;
+ }
+ try {
+ try (BufferedReader reader = Files.newBufferedReader(root,
+ StandardCharsets.UTF_8)) {
+ String line;
+ while (!isFinished() && ((line = reader.readLine()) != null)) {
+ processClass(line);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import sun.management.ManagementFactoryHelper;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import java.util.List;
+import java.util.concurrent.*;
+
+/**
+ * @author igor.ignatyev@oracle.com
+ */
+public class CompileTheWorld {
+ /**
+ * Entry point. Compiles classes in {@code args}, or all classes in
+ * boot-classpath if args is empty
+ *
+ * @param args paths to jar/zip, dir contains classes, or to .lst file
+ * contains list of classes to compile
+ */
+ public static void main(String[] args) {
+ String logfile = Utils.LOG_FILE;
+ PrintStream os = null;
+ if (logfile != null) {
+ try {
+ os = new PrintStream(Files.newOutputStream(Paths.get(logfile)));
+ } catch (IOException io) {
+ }
+ }
+ if (os != null) {
+ System.setOut(os);
+ }
+
+ try {
+ try {
+ if (ManagementFactoryHelper.getCompilationMXBean() == null) {
+ throw new RuntimeException(
+ "CTW can not work in interpreted mode");
+ }
+ } catch (java.lang.NoClassDefFoundError e) {
+ // compact1, compact2 support
+ }
+ String[] paths = args;
+ boolean skipRtJar = false;
+ if (args.length == 0) {
+ paths = getDefaultPaths();
+ skipRtJar = true;
+ }
+ ExecutorService executor = createExecutor();
+ long start = System.currentTimeMillis();
+ try {
+ String path;
+ for (int i = 0, n = paths.length; i < n
+ && !PathHandler.isFinished(); ++i) {
+ path = paths[i];
+ if (skipRtJar && i > 0 && isRtJar(path)) {
+ // rt.jar is not first, so skip it
+ continue;
+ }
+ PathHandler.create(path, executor).process();
+ }
+ } finally {
+ await(executor);
+ }
+ System.out.printf("Done (%d classes, %d methods, %d ms)%n",
+ Compiler.getClassCount(),
+ Compiler.getMethodCount(),
+ System.currentTimeMillis() - start);
+ } finally {
+ if (os != null) {
+ os.close();
+ }
+ }
+ }
+
+ private static ExecutorService createExecutor() {
+ final int threadsCount = Math.min(
+ Runtime.getRuntime().availableProcessors(),
+ Utils.CI_COMPILER_COUNT);
+ ExecutorService result;
+ if (threadsCount > 1) {
+ result = new ThreadPoolExecutor(threadsCount, threadsCount,
+ /* keepAliveTime */ 0L, TimeUnit.MILLISECONDS,
+ new ArrayBlockingQueue<>(threadsCount),
+ new ThreadPoolExecutor.CallerRunsPolicy());
+ } else {
+ result = new CurrentThreadExecutor();
+ }
+ return result;
+ }
+
+ private static String[] getDefaultPaths() {
+ String property = System.getProperty("sun.boot.class.path");
+ System.out.println(
+ "# use 'sun.boot.class.path' as args: " + property);
+ return Utils.PATH_SEPARATOR.split(property);
+ }
+
+ private static void await(ExecutorService executor) {
+ executor.shutdown();
+ while (!executor.isTerminated()) {
+ try {
+ executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+ }
+ }
+
+ private static boolean isRtJar(String path) {
+ return Utils.endsWithIgnoreCase(path, File.separator + "rt.jar");
+ }
+
+ private static class CurrentThreadExecutor extends AbstractExecutorService {
+ private boolean isShutdown;
+
+ @Override
+ public void shutdown() {
+ this.isShutdown = true;
+ }
+
+ @Override
+ public List<Runnable> shutdownNow() {
+ return null;
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return isShutdown;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return isShutdown;
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit)
+ throws InterruptedException {
+ return isShutdown;
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import sun.hotspot.WhiteBox;
+import sun.misc.SharedSecrets;
+import sun.reflect.ConstantPool;
+
+import java.lang.reflect.Executable;
+
+import java.util.Objects;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Provide method to compile whole class.
+ * Also contains compiled methods and classes counters.
+ *
+ * @author igor.ignatyev@oracle.com
+ */
+public class Compiler {
+ private Compiler() { }
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ private static final AtomicLong CLASS_COUNT = new AtomicLong(0L);
+ private static final AtomicLong METHOD_COUNT = new AtomicLong(0L);
+ private static volatile boolean CLASSES_LIMIT_REACHED = false;
+
+ /**
+ * @return count of processed classes
+ */
+ public static long getClassCount() {
+ return CLASS_COUNT.get();
+ }
+
+ /**
+ * @return count of processed methods
+ */
+ public static long getMethodCount() {
+ return METHOD_COUNT.get();
+ }
+
+ /**
+ * @return {@code true} if classes limit is reached
+ */
+ public static boolean isLimitReached() {
+ return CLASSES_LIMIT_REACHED;
+ }
+
+ /**
+ * Compiles all methods and constructors.
+ *
+ * @param aClass class to compile
+ * @param executor executor used for compile task invocation
+ * @throws NullPointerException if {@code class} or {@code executor}
+ * is {@code null}
+ */
+ public static void compileClass(Class aClass, Executor executor) {
+ Objects.requireNonNull(aClass);
+ Objects.requireNonNull(executor);
+ long id = CLASS_COUNT.incrementAndGet();
+ if (id > Utils.COMPILE_THE_WORLD_STOP_AT) {
+ CLASS_COUNT.decrementAndGet();
+ CLASSES_LIMIT_REACHED = true;
+ return;
+ }
+
+ if (id >= Utils.COMPILE_THE_WORLD_START_AT) {
+ String name = aClass.getName();
+ try {
+ System.out.printf("[%d]\t%s%n", id, name);
+ ConstantPool constantPool = SharedSecrets.getJavaLangAccess().
+ getConstantPool(aClass);
+ if (Utils.COMPILE_THE_WORLD_PRELOAD_CLASSES) {
+ preloadClasses(name, id, constantPool);
+ }
+ long methodCount = 0;
+ for (Executable e : aClass.getDeclaredConstructors()) {
+ ++methodCount;
+ executor.execute(new CompileMethodCommand(id, name, e));
+ }
+ for (Executable e : aClass.getDeclaredMethods()) {
+ ++methodCount;
+ executor.execute(new CompileMethodCommand(id, name, e));
+ }
+ METHOD_COUNT.addAndGet(methodCount);
+
+ if (Utils.DEOPTIMIZE_ALL_CLASSES_RATE > 0
+ && (id % Utils.DEOPTIMIZE_ALL_CLASSES_RATE == 0)) {
+ WHITE_BOX.deoptimizeAll();
+ }
+ } catch (Throwable t) {
+ System.out.printf("[%d]\t%s\tskipping %s%n", id, name, t);
+ t.printStackTrace();
+ }
+ }
+ }
+
+ private static void preloadClasses(String className, long id,
+ ConstantPool constantPool) {
+ try {
+ for (int i = 0, n = constantPool.getSize(); i < n; ++i) {
+ try {
+ constantPool.getClassAt(i);
+ } catch (IllegalArgumentException ignore) {
+ }
+ }
+ } catch (Throwable t) {
+ System.out.printf("[%d]\t%s\tpreloading failed : %s%n", id,
+ className, t);
+ }
+ }
+
+
+
+ /**
+ * Compilation of method.
+ * Will compile method on all available comp levels.
+ */
+ private static class CompileMethodCommand implements Runnable {
+ private final long classId;
+ private final String className;
+ private final Executable method;
+
+ /**
+ * @param classId id of class
+ * @param className name of class
+ * @param method compiled for compilation
+ */
+ public CompileMethodCommand(long classId, String className,
+ Executable method) {
+ this.classId = classId;
+ this.className = className;
+ this.method = method;
+ }
+
+ @Override
+ public final void run() {
+ int compLevel = Utils.INITIAL_COMP_LEVEL;
+ if (Utils.TIERED_COMPILATION) {
+ for (int i = compLevel; i <= Utils.TIERED_STOP_AT_LEVEL; ++i) {
+ WHITE_BOX.deoptimizeMethod(method);
+ compileMethod(method, i);
+ }
+ } else {
+ compileMethod(method, compLevel);
+ }
+ }
+
+ private void waitCompilation() {
+ if (!Utils.BACKGROUND_COMPILATION) {
+ return;
+ }
+ final Object obj = new Object();
+ synchronized (obj) {
+ for (int i = 0;
+ i < 10 && WHITE_BOX.isMethodQueuedForCompilation(method);
+ ++i) {
+ try {
+ obj.wait(1000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+ }
+
+ private void compileMethod(Executable method, int compLevel) {
+ if (WHITE_BOX.isMethodCompilable(method, compLevel)) {
+ try {
+ WHITE_BOX.enqueueMethodForCompilation(method, compLevel);
+ waitCompilation();
+ int tmp = WHITE_BOX.getMethodCompilationLevel(method);
+ if (tmp != compLevel) {
+ logMethod(method, "compilation level = " + tmp
+ + ", but not " + compLevel);
+ } else if (Utils.IS_VERBOSE) {
+ logMethod(method, "compilation level = " + tmp + ". OK");
+ }
+ } catch (Throwable t) {
+ logMethod(method, "error on compile at " + compLevel
+ + " level");
+ t.printStackTrace();
+ }
+ } else if (Utils.IS_VERBOSE) {
+ logMethod(method, "not compilable at " + compLevel);
+ }
+ }
+
+ private void logMethod(Executable method, String message) {
+ StringBuilder builder = new StringBuilder("[");
+ builder.append(classId);
+ builder.append("]\t");
+ builder.append(className);
+ builder.append("::");
+ builder.append(method.getName());
+ builder.append('(');
+ Class[] params = method.getParameterTypes();
+ for (int i = 0, n = params.length - 1; i < n; ++i) {
+ builder.append(params[i].getName());
+ builder.append(", ");
+ }
+ if (params.length != 0) {
+ builder.append(params[params.length - 1].getName());
+ }
+ builder.append(')');
+ if (message != null) {
+ builder.append('\t');
+ builder.append(message);
+ }
+ System.err.println(builder);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.io.File;
+
+import java.util.Objects;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.concurrent.Executor;
+
+/**
+ * Abstract handler for path.
+ * <p/>
+ * Concrete subclasses should implement method {@link #process()}.
+ *
+ * @author igor.ignatyev@oracle.com
+ */
+public abstract class PathHandler {
+ private static final Pattern JAR_IN_DIR_PATTERN
+ = Pattern.compile("^(.*[/\\\\])?\\*$");
+ protected final Path root;
+ protected final Executor executor;
+ private ClassLoader loader;
+
+ /**
+ * @param root root path to process
+ * @param executor executor used for process task invocation
+ * @throws NullPointerException if {@code root} or {@code executor} is
+ * {@code null}
+ */
+ protected PathHandler(Path root, Executor executor) {
+ Objects.requireNonNull(root);
+ Objects.requireNonNull(executor);
+ this.root = root.normalize();
+ this.executor = executor;
+ this.loader = ClassLoader.getSystemClassLoader();
+ }
+
+ /**
+ * Factory method. Construct concrete handler in depends from {@code path}.
+ *
+ * @param path the path to process
+ * @param executor executor used for compile task invocation
+ * @throws NullPointerException if {@code path} or {@code executor} is
+ * {@code null}
+ */
+ public static PathHandler create(String path, Executor executor) {
+ Objects.requireNonNull(path);
+ Objects.requireNonNull(executor);
+ Matcher matcher = JAR_IN_DIR_PATTERN.matcher(path);
+ if (matcher.matches()) {
+ path = matcher.group(1);
+ path = path.isEmpty() ? "." : path;
+ return new ClassPathJarInDirEntry(Paths.get(path), executor);
+ } else {
+ path = path.isEmpty() ? "." : path;
+ Path p = Paths.get(path);
+ if (isJarFile(p)) {
+ return new ClassPathJarEntry(p, executor);
+ } else if (isListFile(p)) {
+ return new ClassesListInFile(p, executor);
+ } else {
+ return new ClassPathDirEntry(p, executor);
+ }
+ }
+ }
+
+ private static boolean isJarFile(Path path) {
+ if (Files.isRegularFile(path)) {
+ String name = path.toString();
+ return Utils.endsWithIgnoreCase(name, ".zip")
+ || Utils.endsWithIgnoreCase(name, ".jar");
+ }
+ return false;
+ }
+
+ private static boolean isListFile(Path path) {
+ if (Files.isRegularFile(path)) {
+ String name = path.toString();
+ return Utils.endsWithIgnoreCase(name, ".lst");
+ }
+ return false;
+ }
+
+ /**
+ * Processes all classes in specified path.
+ */
+ public abstract void process();
+
+ /**
+ * Sets class loader, that will be used to define class at
+ * {@link #processClass(String)}.
+ *
+ * @param loader class loader
+ * @throws NullPointerException if {@code loader} is {@code null}
+ */
+ protected final void setLoader(ClassLoader loader) {
+ Objects.requireNonNull(loader);
+ this.loader = loader;
+ }
+
+ /**
+ * Processes specificed class.
+ * @param name fully qualified name of class to process
+ */
+ protected final void processClass(String name) {
+ try {
+ Class aClass = Class.forName(name, true, loader);
+ Compiler.compileClass(aClass, executor);
+ } catch (ClassNotFoundException | LinkageError e) {
+ System.out.printf("Class %s loading failed : %s%n", name,
+ e.getMessage());
+ }
+ }
+
+ /**
+ * @return {@code true} if processing should be stopped
+ */
+ public static boolean isFinished() {
+ return Compiler.isLimitReached();
+ }
+
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2013, 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.tools.ctw;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import sun.management.ManagementFactoryHelper;
+
+import java.io.File;
+import java.util.regex.Pattern;
+
+/**
+ * Auxiliary methods.
+ *
+ * @author igor.ignatyev@oracle.com
+ */
+public class Utils {
+ /**
+ * Value of {@code -XX:CompileThreshold}
+ */
+ public static final boolean TIERED_COMPILATION
+ = Boolean.parseBoolean(getVMOption("TieredCompilation", "false"));
+ /**
+ * Value of {@code -XX:BackgroundCompilation}
+ */
+ public static final boolean BACKGROUND_COMPILATION
+ = Boolean.parseBoolean(getVMOption("BackgroundCompilation",
+ "false"));
+ /**
+ * Value of {@code -XX:TieredStopAtLevel}
+ */
+ public static final int TIERED_STOP_AT_LEVEL;
+ /**
+ * Value of {@code -XX:CICompilerCount}
+ */
+ public static final Integer CI_COMPILER_COUNT
+ = Integer.valueOf(getVMOption("CICompilerCount", "1"));
+ /**
+ * Initial compilation level.
+ */
+ public static final int INITIAL_COMP_LEVEL;
+ /**
+ * Compiled path-separator regexp.
+ */
+ public static final Pattern PATH_SEPARATOR = Pattern.compile(
+ File.pathSeparator, Pattern.LITERAL);
+ /**
+ * Value of {@code -DDeoptimizeAllClassesRate}. Frequency of
+ * {@code WB.deoptimizeAll()} invocation If it less that {@code 0},
+ * {@code WB.deoptimizeAll()} will not be invoked.
+ */
+ public static final int DEOPTIMIZE_ALL_CLASSES_RATE
+ = Integer.getInteger("DeoptimizeAllClassesRate", -1);
+ /**
+ * Value of {@code -DCompileTheWorldStopAt}. Last class to consider.
+ */
+ public static final long COMPILE_THE_WORLD_STOP_AT
+ = Long.getLong("CompileTheWorldStopAt", Long.MAX_VALUE);
+ /**
+ * Value of {@code -DCompileTheWorldStartAt}. First class to consider.
+ */
+ public static final long COMPILE_THE_WORLD_START_AT
+ = Long.getLong("CompileTheWorldStartAt", 1);
+ /**
+ * Value of {@code -DCompileTheWorldPreloadClasses}. Preload all classes
+ * used by a class before start loading.
+ */
+ public static final boolean COMPILE_THE_WORLD_PRELOAD_CLASSES;
+ /**
+ * Value of {@code -Dsun.hotspot.tools.ctw.verbose}. Verbose output,
+ * adds additional information about compilation.
+ */
+ public static final boolean IS_VERBOSE
+ = Boolean.getBoolean("sun.hotspot.tools.ctw.verbose");
+ /**
+ * Value of {@code -Dsun.hotspot.tools.ctw.logfile}.Path to logfile, if
+ * it's null, cout will be used.
+ */
+ public static final String LOG_FILE
+ = System.getProperty("sun.hotspot.tools.ctw.logfile");
+ static {
+ if (Utils.TIERED_COMPILATION) {
+ INITIAL_COMP_LEVEL = 1;
+ } else {
+ String vmName = System.getProperty("java.vm.name");
+ if (Utils.endsWithIgnoreCase(vmName, " Server VM")) {
+ INITIAL_COMP_LEVEL = 4;
+ } else if (Utils.endsWithIgnoreCase(vmName, " Client VM")
+ || Utils.endsWithIgnoreCase(vmName, " Minimal VM")) {
+ INITIAL_COMP_LEVEL = 1;
+ } else {
+ throw new RuntimeException("Unknown VM: " + vmName);
+ }
+ }
+
+ TIERED_STOP_AT_LEVEL = Integer.parseInt(getVMOption("TieredStopAtLevel",
+ String.valueOf(INITIAL_COMP_LEVEL)));
+ }
+
+ static {
+ String tmp = System.getProperty("CompileTheWorldPreloadClasses");
+ if (tmp == null) {
+ COMPILE_THE_WORLD_PRELOAD_CLASSES = true;
+ } else {
+ COMPILE_THE_WORLD_PRELOAD_CLASSES = Boolean.parseBoolean(tmp);
+ }
+ }
+
+ public static final String CLASSFILE_EXT = ".class";
+
+ private Utils() {
+ }
+
+ /**
+ * Tests if the string ends with the suffix, ignoring case
+ * considerations
+ *
+ * @param string the tested string
+ * @param suffix the suffix
+ * @return {@code true} if {@code string} ends with the {@code suffix}
+ * @see String#endsWith(String)
+ */
+ public static boolean endsWithIgnoreCase(String string, String suffix) {
+ if (string == null || suffix == null) {
+ return false;
+ }
+ int length = suffix.length();
+ int toffset = string.length() - length;
+ if (toffset < 0) {
+ return false;
+ }
+ return string.regionMatches(true, toffset, suffix, 0, length);
+ }
+
+ /**
+ * Returns value of VM option.
+ *
+ * @param name option's name
+ * @return value of option or {@code null}, if option doesn't exist
+ * @throws NullPointerException if name is null
+ */
+ public static String getVMOption(String name) {
+ String result;
+ HotSpotDiagnosticMXBean diagnostic
+ = ManagementFactoryHelper.getDiagnosticMXBean();
+ result = diagnostic.getVMOption(name).getValue();
+ return result;
+ }
+
+ /**
+ * Returns value of VM option or default value.
+ *
+ * @param name option's name
+ * @param defaultValue default value
+ * @return value of option or {@code defaultValue}, if option doesn't exist
+ * @throws NullPointerException if name is null
+ * @see #getVMOption(String)
+ */
+ public static String getVMOption(String name, String defaultValue) {
+ String result;
+ try {
+ result = getVMOption(name);
+ } catch (NoClassDefFoundError e) {
+ // compact1, compact2 support
+ result = defaultValue;
+ }
+ return result == null ? defaultValue : result;
+ }
+
+ /**
+ * Tests if the filename is valid filename for class file.
+ *
+ * @param filename tested filename
+ */
+ public static boolean isClassFile(String filename) {
+ // If the filename has a period after removing '.class', it's not valid class file
+ return endsWithIgnoreCase(filename, CLASSFILE_EXT)
+ && (filename.indexOf('.')
+ == (filename.length() - CLASSFILE_EXT.length()));
+ }
+
+ /**
+ * Converts the filename to classname.
+ *
+ * @param filename filename to convert
+ * @return corresponding classname.
+ * @throws AssertionError if filename isn't valid filename for class file -
+ * {@link #isClassFile(String)}
+ */
+ public static String fileNameToClassName(String filename) {
+ assert isClassFile(filename);
+ return filename.substring(0, filename.length() - CLASSFILE_EXT.length())
+ .replace(File.separatorChar, '.');
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/Bar.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,5 @@
+public class Bar {
+ private static void staticMethod() { }
+ public void method() { }
+ protected Bar() { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 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 ClassesDirTest
+ * @bug 8012447
+ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
+ * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesDirTest Foo Bar
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * @run main ClassesDirTest prepare
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes
+ * @run main ClassesDirTest check ctw.log
+ * @summary testing of CompileTheWorld :: classes in directory
+ * @author igor.ignatyev@oracle.com
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+public class ClassesDirTest extends CtwTest {
+ private static final String[] SHOULD_CONTAIN
+ = {"# dir: classes", "Done (2 classes, 6 methods, "};
+
+ private ClassesDirTest() {
+ super(SHOULD_CONTAIN);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new ClassesDirTest().run(args);
+ }
+
+ protected void prepare() throws Exception {
+ String path = "classes";
+ Files.createDirectory(Paths.get(path));
+ Files.move(Paths.get("Foo.class"), Paths.get(path, "Foo.class"),
+ StandardCopyOption.REPLACE_EXISTING);
+ Files.move(Paths.get("Bar.class"), Paths.get(path, "Bar.class"),
+ StandardCopyOption.REPLACE_EXISTING);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/ClassesListTest.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013, 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 ClassesListTest
+ * @bug 8012447
+ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
+ * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesListTest Foo Bar
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * @run main ClassesListTest prepare
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst
+ * @run main ClassesListTest check ctw.log
+ * @summary testing of CompileTheWorld :: list of classes in file
+ * @author igor.ignatyev@oracle.com
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+public class ClassesListTest extends CtwTest {
+ private static final String[] SHOULD_CONTAIN
+ = {"# list: classes.lst", "Done (4 classes, "};
+
+ private ClassesListTest() {
+ super(SHOULD_CONTAIN);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new ClassesListTest().run(args);
+ }
+
+ protected void prepare() throws Exception {
+ String path = "classes.lst";
+ Files.copy(Paths.get(System.getProperty("test.src"), path),
+ Paths.get(path), StandardCopyOption.REPLACE_EXISTING);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/CtwTest.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.List;
+import java.util.Collections;
+import java.util.ArrayList;
+
+import java.io.File;
+import java.io.Writer;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.BufferedReader;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.nio.charset.Charset;
+
+import com.oracle.java.testlibrary.JDKToolFinder;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public abstract class CtwTest {
+ protected final String[] shouldContain;
+ protected CtwTest(String[] shouldContain) {
+ this.shouldContain = shouldContain;
+ }
+
+ public void run(String[] args) throws Exception {
+ if (args.length == 0) {
+ throw new Error("args is empty");
+ }
+ switch (args[0]) {
+ case "prepare":
+ prepare();
+ break;
+ case "check":
+ check(args);
+ break;
+ default:
+ throw new Error("unregonized action -- " + args[0]);
+ }
+ }
+
+ protected void prepare() throws Exception { }
+
+ protected void check(String[] args) throws Exception {
+ if (args.length < 2) {
+ throw new Error("logfile isn't specified");
+ }
+ String logfile = args[1];
+ try (BufferedReader r = Files.newBufferedReader(Paths.get(logfile),
+ Charset.defaultCharset())) {
+ OutputAnalyzer output = readOutput(r);
+ for (String test : shouldContain) {
+ output.shouldContain(test);
+ }
+ }
+ }
+
+ private static OutputAnalyzer readOutput(BufferedReader reader)
+ throws IOException {
+ StringBuilder builder = new StringBuilder();
+ String eol = String.format("%n");
+ String line;
+
+ while ((line = reader.readLine()) != null) {
+ builder.append(line);
+ builder.append(eol);
+ }
+ return new OutputAnalyzer(builder.toString(), "");
+ }
+
+ protected void dump(OutputAnalyzer output, String name) {
+ try (Writer w = new FileWriter(name + ".out")) {
+ String s = output.getStdout();
+ w.write(s, s.length(), 0);
+ } catch (IOException io) {
+ io.printStackTrace();
+ }
+ try (Writer w = new FileWriter(name + ".err")) {
+ String s = output.getStderr();
+ w.write(s, s.length(), 0);
+ } catch (IOException io) {
+ io.printStackTrace();
+ }
+ }
+
+ protected ProcessBuilder createJarProcessBuilder(String... command)
+ throws Exception {
+ String javapath = JDKToolFinder.getJDKTool("jar");
+
+ ArrayList<String> args = new ArrayList<>();
+ args.add(javapath);
+ Collections.addAll(args, command);
+
+ return new ProcessBuilder(args.toArray(new String[args.size()]));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/Foo.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,5 @@
+public class Foo {
+ private static void staticMethod() { }
+ public void method() { }
+ protected Foo() { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/JarDirTest.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, 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 JarDirTest
+ * @bug 8012447
+ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
+ * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarDirTest Foo Bar
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * @run main JarDirTest prepare
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/*
+ * @run main JarDirTest check ctw.log
+ * @summary testing of CompileTheWorld :: jars in directory
+ * @author igor.ignatyev@oracle.com
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class JarDirTest extends CtwTest {
+ private static final String[] SHOULD_CONTAIN
+ = {"# jar_in_dir: jars",
+ "# jar: jars" + File.separator +"foo.jar",
+ "# jar: jars" + File.separator +"bar.jar",
+ "Done (4 classes, 12 methods, "};
+
+ private JarDirTest() {
+ super(SHOULD_CONTAIN);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new JarDirTest().run(args);
+ }
+
+ protected void prepare() throws Exception {
+ String path = "jars";
+ Files.createDirectory(Paths.get(path));
+
+ ProcessBuilder pb = createJarProcessBuilder("cf", "jars/foo.jar",
+ "Foo.class", "Bar.class");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ dump(output, "ctw-foo.jar");
+ output.shouldHaveExitValue(0);
+
+ pb = createJarProcessBuilder("cf", "jars/bar.jar", "Foo.class",
+ "Bar.class");
+ output = new OutputAnalyzer(pb.start());
+ dump(output, "ctw-bar.jar");
+ output.shouldHaveExitValue(0);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/JarsTest.java Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, 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 JarsTest
+ * @bug 8012447
+ * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
+ * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarsTest Foo Bar
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * @run main JarsTest prepare
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar
+ * @run main JarsTest check ctw.log
+ * @summary testing of CompileTheWorld :: jars
+ * @author igor.ignatyev@oracle.com
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class JarsTest extends CtwTest {
+ private static final String[] SHOULD_CONTAIN
+ = {"# jar: foo.jar", "# jar: bar.jar",
+ "Done (4 classes, 12 methods, "};
+
+ private JarsTest() {
+ super(SHOULD_CONTAIN);
+ }
+
+ public static void main(String[] args) throws Exception {
+ new JarsTest().run(args);
+ }
+
+ protected void prepare() throws Exception {
+ ProcessBuilder pb = createJarProcessBuilder("cf", "foo.jar",
+ "Foo.class", "Bar.class");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ dump(output, "ctw-foo.jar");
+ output.shouldHaveExitValue(0);
+
+ pb = createJarProcessBuilder("cf", "bar.jar", "Foo.class", "Bar.class");
+ output = new OutputAnalyzer(pb.start());
+ dump(output, "ctw-bar.jar");
+ output.shouldHaveExitValue(0);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/ctw/test/classes.lst Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,4 @@
+java.lang.String
+java.lang.Object
+Foo
+Bar
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/testlibrary/whitebox/Makefile Mon Sep 09 19:53:28 2013 +0200
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2013, 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.
+#
+#
+
+ifneq "x$(ALT_BOOTDIR)" "x"
+ BOOTDIR := $(ALT_BOOTDIR)
+endif
+
+ifeq "x$(BOOTDIR)" "x"
+ JDK_HOME := $(shell dirname $(shell which java))/..
+else
+ JDK_HOME := $(BOOTDIR)
+endif
+
+SRC_DIR = ./
+BUILD_DIR = build
+OUTPUT_DIR = $(BUILD_DIR)/classes
+
+JAVAC = $(JDK_HOME)/bin/javac
+JAR = $(JDK_HOME)/bin/jar
+
+SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
+
+.PHONY: filelist clean cleantmp
+
+all: wb.jar cleantmp
+
+wb.jar: filelist
+ @mkdir -p $(OUTPUT_DIR)
+ $(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp $(OUTPUT_DIR) @filelist
+ $(JAR) cf wb.jar -C $(OUTPUT_DIR) .
+ @rm -rf $(OUTPUT_DIR)
+
+filelist: $(SRC_FILES)
+ @rm -f $@
+ @echo $(SRC_FILES) > $@
+
+clean: cleantmp
+ @rm -rf wb.jar
+
+cleantmp:
+ @rm -rf filelist
+ @rm -rf $(BUILD_DIR)