mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-22 12:04:39 +02:00
8012447: Java CTW implementation
Reviewed-by: vlivanov, kvn, twisti
This commit is contained in:
parent
547f4dea7b
commit
c73d393947
21 changed files with 1752 additions and 18 deletions
|
@ -48,7 +48,7 @@ public class TestVerifyDuringStartup {
|
||||||
"-XX:+VerifyDuringStartup",
|
"-XX:+VerifyDuringStartup",
|
||||||
"-version"});
|
"-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) {
|
for (int i = 0; i < vmOpts.size(); i += 1) {
|
||||||
System.out.print(" " + vmOpts.get(i));
|
System.out.print(" " + vmOpts.get(i));
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,37 @@ public final class JDKToolFinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the full path to an executable in jdk/bin based on System property
|
* Returns the full path to an executable in jdk/bin based on System
|
||||||
* test.jdk (set by jtreg test suite)
|
* property {@code compile.jdk} (set by jtreg test suite)
|
||||||
*
|
*
|
||||||
* @return Full path to an executable in jdk/bin
|
* @return Full path to an executable in jdk/bin
|
||||||
*/
|
*/
|
||||||
public static String getJDKTool(String tool) {
|
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;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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");
|
String binPath = System.getProperty("test.jdk");
|
||||||
if (binPath == null) {
|
if (binPath == null) {
|
||||||
throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. "
|
throw new RuntimeException("System property 'test.jdk' not set. "
|
||||||
+ "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'.");
|
+ "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;
|
binPath += File.separatorChar + "bin" + File.separatorChar + tool;
|
||||||
|
|
||||||
return binPath;
|
return binPath;
|
||||||
|
|
73
hotspot/test/testlibrary/ctw/Makefile
Normal file
73
hotspot/test/testlibrary/ctw/Makefile
Normal file
|
@ -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
|
93
hotspot/test/testlibrary/ctw/README
Normal file
93
hotspot/test/testlibrary/ctw/README
Normal file
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -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, '.');
|
||||||
|
}
|
||||||
|
}
|
5
hotspot/test/testlibrary/ctw/test/Bar.java
Normal file
5
hotspot/test/testlibrary/ctw/test/Bar.java
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
public class Bar {
|
||||||
|
private static void staticMethod() { }
|
||||||
|
public void method() { }
|
||||||
|
protected Bar() { }
|
||||||
|
}
|
61
hotspot/test/testlibrary/ctw/test/ClassesDirTest.java
Normal file
61
hotspot/test/testlibrary/ctw/test/ClassesDirTest.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
58
hotspot/test/testlibrary/ctw/test/ClassesListTest.java
Normal file
58
hotspot/test/testlibrary/ctw/test/ClassesListTest.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
118
hotspot/test/testlibrary/ctw/test/CtwTest.java
Normal file
118
hotspot/test/testlibrary/ctw/test/CtwTest.java
Normal file
|
@ -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()]));
|
||||||
|
}
|
||||||
|
}
|
5
hotspot/test/testlibrary/ctw/test/Foo.java
Normal file
5
hotspot/test/testlibrary/ctw/test/Foo.java
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
public class Foo {
|
||||||
|
private static void staticMethod() { }
|
||||||
|
public void method() { }
|
||||||
|
protected Foo() { }
|
||||||
|
}
|
75
hotspot/test/testlibrary/ctw/test/JarDirTest.java
Normal file
75
hotspot/test/testlibrary/ctw/test/JarDirTest.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
hotspot/test/testlibrary/ctw/test/JarsTest.java
Normal file
65
hotspot/test/testlibrary/ctw/test/JarsTest.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
4
hotspot/test/testlibrary/ctw/test/classes.lst
Normal file
4
hotspot/test/testlibrary/ctw/test/classes.lst
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
java.lang.String
|
||||||
|
java.lang.Object
|
||||||
|
Foo
|
||||||
|
Bar
|
63
hotspot/test/testlibrary/whitebox/Makefile
Normal file
63
hotspot/test/testlibrary/whitebox/Makefile
Normal file
|
@ -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)
|
Loading…
Add table
Add a link
Reference in a new issue