--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java Tue Aug 08 22:58:44 2017 +0200
@@ -23,104 +23,73 @@
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.*;
+import java.io.IOException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
/**
* Handler for dirs containing classes to compile.
*/
-public class ClassPathDirEntry extends PathHandler {
-
- private final int rootLength = root.toString().length();
+public class ClassPathDirEntry extends PathHandler.PathEntry {
+ private final int rootLength;
- public ClassPathDirEntry(Path root, Executor executor) {
- super(root, executor);
+ public ClassPathDirEntry(Path root) {
+ super(root);
+ if (!Files.exists(root)) {
+ throw new Error(root + " dir does not exist");
+ }
+ rootLength = root.toString()
+ .length();
+ }
+
+ @Override
+ protected Stream<String> classes() {
try {
- URL url = root.toUri().toURL();
- setLoader(new URLClassLoader(new URL[]{url}));
- } catch (MalformedURLException e) {
- e.printStackTrace();
+ return Files.walk(root, Integer.MAX_VALUE, FileVisitOption.FOLLOW_LINKS)
+ .filter(p -> Utils.isClassFile(p.toString()))
+ .map(this::pathToClassName);
+ } catch (IOException e) {
+ throw new Error("can not traverse " + root + " : " + e.getMessage(), e);
}
}
@Override
- public void process() {
- CompileTheWorld.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();
- }
+ protected String description() {
+ return "# dir: " + root;
}
@Override
- public long classCount() {
+ protected byte[] findByteCode(String classname) {
+ Path path = root;
+ for (String c : Utils.classNameToFileName(classname).split("/")) {
+ path = path.resolve(c);
+ }
+ if (!path.toFile()
+ .exists()) {
+ return null;
+ }
try {
- return Files.walk(root, FileVisitOption.FOLLOW_LINKS).count();
+ return Files.readAllBytes(path);
} catch (IOException e) {
- throw new Error("can not walk dir " + root + " : "
- + e.getMessage(), e);
- }
- }
-
- private void processFile(Path file) {
- if (Utils.isClassFile(file.toString())) {
- processClass(pathToClassName(file));
+ e.printStackTrace(CompileTheWorld.ERR);
+ return null;
}
}
private String pathToClassName(Path file) {
String fileString;
if (root == file) {
- fileString = file.normalize().toString();
+ fileString = file.normalize()
+ .toString();
} else {
- fileString = file.normalize().toString().substring(rootLength + 1);
+ 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;
- }
- }
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java Tue Aug 08 22:58:44 2017 +0200
@@ -23,69 +23,62 @@
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.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Stream;
/**
* Handler for jar-files containing classes to compile.
*/
-public class ClassPathJarEntry extends PathHandler {
+public class ClassPathJarEntry extends PathHandler.PathEntry {
+ private final JarFile jarFile;
- public ClassPathJarEntry(Path root, Executor executor) {
- super(root, executor);
+ public ClassPathJarEntry(Path root) {
+ super(root);
+ if (!Files.exists(root)) {
+ throw new Error(root + " file not found");
+ }
try {
- URL url = root.toUri().toURL();
- setLoader(new URLClassLoader(new URL[]{url}));
- } catch (MalformedURLException e) {
- e.printStackTrace();
+ jarFile = new JarFile(root.toFile());
+ } catch (IOException e) {
+ throw new Error("can not read " + root + " : " + e.getMessage(), e);
}
}
@Override
- public void process() {
- CompileTheWorld.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();
- }
+ protected Stream<String> classes() {
+ return jarFile.stream()
+ .map(JarEntry::getName)
+ .filter(Utils::isClassFile)
+ .map(Utils::fileNameToClassName);
+ }
+
+ @Override
+ protected String description() {
+ return "# jar: " + root;
}
@Override
- public long classCount() {
- try (JarFile jarFile = new JarFile(root.toFile())) {
- return jarFile.stream()
- .map(JarEntry::getName)
- .filter(Utils::isClassFile)
- .count();
+ protected byte[] findByteCode(String classname) {
+ try {
+ String filename = Utils.classNameToFileName(classname);
+ JarEntry entry = jarFile.getJarEntry(filename);
+
+ if (entry == null) {
+ return null;
+ }
+
+ try (InputStream is = jarFile.getInputStream(entry)) {
+ return is.readAllBytes();
+ }
+
} catch (IOException e) {
- throw new Error("can not open jar file " + root + " : "
- + e.getMessage() , e);
- }
- }
-
- private void processJarEntry(JarEntry entry) {
- String filename = entry.getName();
- if (Utils.isClassFile(filename)) {
- processClass(Utils.fileNameToClassName(filename));
+ e.printStackTrace(CompileTheWorld.ERR);
+ return null;
}
}
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java Tue Aug 08 22:58:44 2017 +0200
@@ -27,46 +27,52 @@
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.concurrent.Executor;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* Handler for dirs containing jar-files with classes to compile.
*/
-public class ClassPathJarInDirEntry extends PathHandler {
-
- public ClassPathJarInDirEntry(Path root, Executor executor) {
- super(root, executor);
- }
-
- @Override
- public void process() {
- CompileTheWorld.OUT.println("# jar_in_dir: " + root);
- if (!Files.exists(root)) {
- return;
+public class ClassPathJarInDirEntry {
+ public static List<PathHandler> create(Path path) {
+ Objects.requireNonNull(path);
+ if (!Files.exists(path)) {
+ throw new Error(path + " directory not found");
}
- 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();
+ try {
+ return Stream.concat(
+ Stream.of(new PathHandler(new JarInDirEntry(path))),
+ Files.list(path)
+ .filter(p -> p.getFileName().toString().endsWith(".jar"))
+ .map(ClassPathJarEntry::new)
+ .map(PathHandler::new))
+ .collect(Collectors.toList());
+ } catch (IOException e) {
+ throw new Error("can not read " + path + " directory : " + e.getMessage(), e);
}
}
- @Override
- public long classCount() {
- try {
- return Files.list(root)
- .filter(p -> p.getFileName().toString().endsWith(".jar"))
- .map(p -> new ClassPathJarEntry(p, executor))
- .mapToLong(ClassPathJarEntry::classCount).sum();
- } catch (IOException e) {
- throw new Error("can not walk dir " + root + " : "
- + e.getMessage(), e);
+ // dummy path handler, used just to print description before real handlers.
+ private static class JarInDirEntry extends PathHandler.PathEntry {
+ private JarInDirEntry(Path root) {
+ super(root);
+ }
+
+ @Override
+ protected byte[] findByteCode(String name) {
+ return null;
+ }
+
+ @Override
+ protected Stream<String> classes() {
+ return Stream.empty();
+ }
+
+ @Override
+ protected String description() {
+ return "# jar_in_dir: " + root;
}
}
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java Tue Aug 08 22:58:44 2017 +0200
@@ -24,58 +24,69 @@
package sun.hotspot.tools.ctw;
import jdk.internal.jimage.ImageReader;
+import jdk.internal.jimage.ImageLocation;
import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.concurrent.Executor;
+import java.util.stream.Stream;
/**
* Handler for jimage-files containing classes to compile.
*/
-public class ClassPathJimageEntry extends PathHandler {
- public ClassPathJimageEntry(Path root, Executor executor) {
- super(root, executor);
+public class ClassPathJimageEntry extends PathHandler.PathEntry {
+
+ @Override
+ protected Stream<String> classes() {
+ return Arrays.stream(reader.getEntryNames())
+ .filter(name -> name.endsWith(".class"))
+ .filter(name -> !name.endsWith("module-info.class"))
+ .map(Utils::fileNameToClassName);
+ }
+
+ @Override
+ protected String description() {
+ return "# jimage: " + root;
+ }
+
+ @Override
+ public void close() {
try {
- URL url = root.toUri().toURL();
- setLoader(new URLClassLoader(new URL[]{url}));
- } catch (MalformedURLException e) {
- e.printStackTrace();
+ reader.close();
+ } catch (IOException e) {
+ throw new Error("error on closing reader for " + root + " : "
+ + e.getMessage(), e);
+ } finally {
+ super.close();
+ }
+ }
+
+ private final ImageReader reader;
+
+ public ClassPathJimageEntry(Path root) {
+ super(root);
+ if (!Files.exists(root)) {
+ throw new Error(root + " image file not found");
+ }
+ try {
+ reader = ImageReader.open(root);
+ } catch (IOException e) {
+ throw new Error("can not open " + root + " : " + e.getMessage(), e);
}
}
@Override
- public void process() {
- CompileTheWorld.OUT.println("# jimage: " + root);
- if (!Files.exists(root)) {
- return;
+ protected byte[] findByteCode(String name) {
+ String resource = Utils.classNameToFileName(name);
+ for (String m : reader.getModuleNames()) {
+ ImageLocation location = reader.findLocation(m, resource);
+ if (location != null) {
+ return reader.getResource(location);
+ }
}
- try (ImageReader reader = ImageReader.open(root)) {
- Arrays.stream(reader.getEntryNames())
- .filter(name -> name.endsWith(".class"))
- .filter(name -> !name.endsWith("module-info.class"))
- .map(Utils::fileNameToClassName)
- .forEach(this::processClass);
- } catch (IOException ioe) {
- ioe.printStackTrace();
- }
+ return null;
}
- @Override
- public long classCount() {
- try (ImageReader reader = ImageReader.open(root)) {
- return Arrays.stream(reader.getEntryNames())
- .filter(name -> name.endsWith(".class"))
- .filter(name -> !name.endsWith("module-info.class"))
- .map(Utils::fileNameToClassName)
- .count();
- } catch (IOException e) {
- throw new Error("can not open jimage file " + root + " : "
- + e.getMessage() , e);
- }
- }
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java Tue Aug 08 22:58:44 2017 +0200
@@ -25,46 +25,52 @@
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;
+import java.util.stream.Stream;
/**
* Handler for files containing a list of classes to compile.
*/
-public class ClassesListInFile extends PathHandler {
- public ClassesListInFile(Path root, Executor executor) {
- super(root, executor);
- }
+public class ClassesListInFile extends PathHandler.PathEntry {
+ private final BufferedReader reader;
- @Override
- public void process() {
- CompileTheWorld.OUT.println("# list: " + root);
+ public ClassesListInFile(Path root) {
+ super(root);
if (!Files.exists(root)) {
- return;
+ throw new Error(root + " file does not exist");
}
try {
- try (BufferedReader reader = Files.newBufferedReader(root)) {
- String line;
- while (!isFinished() && ((line = reader.readLine()) != null)) {
- processClass(line);
- }
- }
+ reader = Files.newBufferedReader(root);
} catch (IOException e) {
- e.printStackTrace();
+ throw new Error("can not open " + root + " : " + e.getMessage(), e);
}
}
@Override
- public long classCount() {
+ protected byte[] findByteCode(String name) {
+ return null;
+ }
+
+ @Override
+ protected Stream<String> classes() {
+ return reader.lines();
+ }
+
+ @Override
+ protected String description() {
+ return "# list: " + root;
+ }
+
+ @Override
+ public void close() {
try {
- try (BufferedReader reader = Files.newBufferedReader(root)) {
- return reader.lines().count();
- }
+ reader.close();
} catch (IOException e) {
- throw new Error("can not read list " + root + " : "
- + e.getMessage(), e);
+ throw new Error("error on closing reader for " + root
+ + " : " + e.getMessage(), e);
+ } finally {
+ super.close();
}
}
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Tue Aug 08 22:58:44 2017 +0200
@@ -29,6 +29,7 @@
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
@@ -73,12 +74,16 @@
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];
- PathHandler.create(path, executor).process();
- }
+ Arrays.stream(paths)
+ .map(PathHandler::create)
+ .flatMap(List::stream)
+ .forEach(p -> {
+ try {
+ p.process(executor);
+ } finally {
+ p.close();
+ }
+ });
} finally {
await(executor);
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java Tue Aug 08 22:58:44 2017 +0200
@@ -23,14 +23,17 @@
package sun.hotspot.tools.ctw;
-import sun.hotspot.WhiteBox;
import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.Unsafe;
import jdk.internal.reflect.ConstantPool;
+import sun.hotspot.WhiteBox;
+
import java.lang.reflect.Executable;
-
+import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
/**
* Provide method to compile whole class.
@@ -38,6 +41,7 @@
*/
public class Compiler {
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final AtomicLong METHOD_COUNT = new AtomicLong(0L);
@@ -62,35 +66,27 @@
public static void compileClass(Class<?> aClass, long id, Executor executor) {
Objects.requireNonNull(aClass);
Objects.requireNonNull(executor);
- try {
- ConstantPool constantPool = SharedSecrets.getJavaLangAccess().
- getConstantPool(aClass);
- if (Utils.COMPILE_THE_WORLD_PRELOAD_CLASSES) {
- preloadClasses(aClass.getName(), id, constantPool);
- }
- int startLevel = Utils.INITIAL_COMP_LEVEL;
- int endLevel = Utils.TIERED_COMPILATION ? Utils.TIERED_STOP_AT_LEVEL : startLevel;
- for (int i = startLevel; i <= endLevel; ++i) {
- WHITE_BOX.enqueueInitializerForCompilation(aClass, i);
- }
- long methodCount = 0;
- for (Executable e : aClass.getDeclaredConstructors()) {
- ++methodCount;
- executor.execute(new CompileMethodCommand(id, e));
- }
- for (Executable e : aClass.getDeclaredMethods()) {
- ++methodCount;
- executor.execute(new CompileMethodCommand(id, e));
- }
- METHOD_COUNT.addAndGet(methodCount);
+ ConstantPool constantPool = SharedSecrets.getJavaLangAccess().
+ getConstantPool(aClass);
+ if (Utils.COMPILE_THE_WORLD_PRELOAD_CLASSES) {
+ preloadClasses(aClass.getName(), id, constantPool);
+ }
+ UNSAFE.ensureClassInitialized(aClass);
+ compileClinit(aClass, id);
+ long methodCount = 0;
+ for (Executable e : aClass.getDeclaredConstructors()) {
+ ++methodCount;
+ executor.execute(new CompileMethodCommand(id, e));
+ }
+ for (Executable e : aClass.getDeclaredMethods()) {
+ ++methodCount;
+ executor.execute(new CompileMethodCommand(id, 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) {
- CompileTheWorld.OUT.printf("[%d]\t%s\tskipping %s%n", id, aClass.getName(), t);
- t.printStackTrace();
+ if (Utils.DEOPTIMIZE_ALL_CLASSES_RATE > 0
+ && (id % Utils.DEOPTIMIZE_ALL_CLASSES_RATE == 0)) {
+ WHITE_BOX.deoptimizeAll();
}
}
@@ -104,12 +100,25 @@
}
}
} catch (Throwable t) {
- CompileTheWorld.OUT.printf("[%d]\t%s\tpreloading failed : %s%n",
+ CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING preloading failed : %s%n",
id, className, t);
+ t.printStackTrace(CompileTheWorld.ERR);
}
}
-
+ private static void compileClinit(Class<?> aClass, long id) {
+ int startLevel = Utils.INITIAL_COMP_LEVEL;
+ int endLevel = Utils.TIERED_COMPILATION ? Utils.TIERED_STOP_AT_LEVEL : startLevel;
+ for (int i = startLevel; i <= endLevel; ++i) {
+ try {
+ WHITE_BOX.enqueueInitializerForCompilation(aClass, i);
+ } catch (Throwable t) {
+ CompileTheWorld.OUT.printf("[%d]\t%s::<clinit>\tERROR at level %d : %s%n",
+ id, aClass.getName(), i, t);
+ t.printStackTrace(CompileTheWorld.ERR);
+ }
+ }
+ }
/**
* Compilation of method.
@@ -168,41 +177,37 @@
waitCompilation();
int tmp = WHITE_BOX.getMethodCompilationLevel(method);
if (tmp != compLevel) {
- log("compilation level = " + tmp
+ log("WARNING compilation level = " + tmp
+ ", but not " + compLevel);
} else if (Utils.IS_VERBOSE) {
log("compilation level = " + tmp + ". OK");
}
} catch (Throwable t) {
- log("error on compile at " + compLevel
- + " level");
- t.printStackTrace();
+ log("ERROR at level " + compLevel);
+ t.printStackTrace(CompileTheWorld.ERR);
}
} else if (Utils.IS_VERBOSE) {
log("not compilable at " + compLevel);
}
}
+ private String methodName() {
+ return String.format("%s::%s(%s)",
+ className,
+ method.getName(),
+ Arrays.stream(method.getParameterTypes())
+ .map(Class::getName)
+ .collect(Collectors.joining(", ")));
+ }
+
private void log(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(')');
+ StringBuilder builder = new StringBuilder("[")
+ .append(classId)
+ .append("]\t")
+ .append(methodName());
if (message != null) {
- builder.append('\t');
- builder.append(message);
+ builder.append('\t')
+ .append(message);
}
CompileTheWorld.ERR.println(builder);
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java Tue Aug 08 22:58:44 2017 +0200
@@ -162,8 +162,12 @@
}
private long classCount() {
- return PathHandler.create(targetPath.toString(), Runnable::run)
- .classCount();
+ List<PathHandler> phs = PathHandler.create(targetPath.toString());
+ long result = phs.stream()
+ .mapToLong(PathHandler::classCount)
+ .sum();
+ phs.forEach(PathHandler::close);
+ return result;
}
private Pair<String, Long> getLastClass(Path errFile) {
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java Tue Aug 08 22:58:44 2017 +0200
@@ -23,73 +23,118 @@
package sun.hotspot.tools.ctw;
-import jdk.internal.misc.Unsafe;
-
+import java.io.Closeable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Stream;
/**
- * Abstract handler for path.
- * Concrete subclasses should implement method {@link #process()}.
+ * Handler for a path, responsible for processing classes in the path.
*/
-public abstract class PathHandler {
- private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+public class PathHandler implements Closeable {
+ public static abstract class PathEntry implements Closeable {
+ private final ClassLoader loader = new PathEntryClassLoader(this::findByteCode);
+
+ /**
+ * returns bytecode for the class
+ * @param name binary name of the class
+ * @return bytecode of the class or null if handler does not have any
+ * code for this name
+ */
+ protected abstract byte[] findByteCode(String name);
+
+ protected final Path root;
+
+ /**
+ * @param root path entry root
+ * @throws NullPointerException if {@code root} is {@code null}
+ */
+ protected PathEntry(Path root) {
+ Objects.requireNonNull(root, "root can not be null");
+ this.root = root.normalize();
+ }
+
+ /**
+ * @return classloader which will be used to define classes
+ */
+ protected final ClassLoader loader() {
+ return loader;
+ }
+
+ /**
+ * @return stream of all classes in the specified path.
+ */
+ protected abstract Stream<String> classes();
+
+ /**
+ * @return string description of the specific path.
+ */
+ protected abstract String description();
+
+ public void close() { }
+
+ }
+
+ private static class PathEntryClassLoader extends java.lang.ClassLoader {
+ private final Function<String, byte[]> findByteCode;
+
+ private PathEntryClassLoader(Function<String, byte[]> findByteCode) {
+ this.findByteCode = findByteCode;
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ byte[] code = findByteCode.apply(name);
+ if (code == null) {
+ return super.findClass(name);
+ } else {
+ return defineClass(name, code, 0, code.length);
+ }
+ }
+ }
+
private static final AtomicLong CLASS_COUNT = new AtomicLong(0L);
private static volatile boolean CLASSES_LIMIT_REACHED = false;
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}.
+ * Factory method. Constructs list of handlers for {@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) {
+ public static List<PathHandler> create(String path) {
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);
+ return ClassPathJarInDirEntry.create(Paths.get(path));
} else {
path = path.isEmpty() ? "." : path;
Path p = Paths.get(path);
+ PathEntry entry;
if (isJarFile(p)) {
- return new ClassPathJarEntry(p, executor);
+ entry = new ClassPathJarEntry(p);
} else if (isListFile(p)) {
- return new ClassesListInFile(p, executor);
+ entry = new ClassesListInFile(p);
} else if (isJimageFile(p)) {
- return new ClassPathJimageEntry(p, executor);
+ entry = new ClassPathJimageEntry(p);
} else {
- return new ClassPathDirEntry(p, executor);
+ entry = new ClassPathDirEntry(p);
}
+ return Collections.singletonList(new PathHandler(entry));
}
}
@@ -117,35 +162,42 @@
return false;
}
+ private final PathEntry entry;
+ protected PathHandler(PathEntry entry) {
+ Objects.requireNonNull(entry);
+ this.entry = entry;
+ }
+
+
+ @Override
+ public void close() {
+ entry.close();
+ }
+
/**
* Processes all classes in the specified path.
+ * @param executor executor used for process task invocation
*/
- public abstract void process();
+ public final void process(Executor executor) {
+ CompileTheWorld.OUT.println(entry.description());
+ entry.classes().forEach(s -> processClass(s, executor));
+ }
/**
* @return count of all classes in the specified path.
*/
- public abstract long classCount();
+ public long classCount() {
+ return entry.classes().count();
+ }
- /**
- * 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 specified class.
* @param name fully qualified name of class to process
*/
- protected final void processClass(String name) {
+ protected final void processClass(String name, Executor executor) {
Objects.requireNonNull(name);
- if (CLASSES_LIMIT_REACHED) {
+ if (isFinished()) {
return;
}
long id = CLASS_COUNT.incrementAndGet();
@@ -154,18 +206,16 @@
return;
}
if (id >= Utils.COMPILE_THE_WORLD_START_AT) {
+ Class<?> aClass;
+ Thread.currentThread().setContextClassLoader(entry.loader());
try {
- Class<?> aClass = loader.loadClass(name);
- if (!"sun.reflect.misc.Trampoline".equals(name)
- // workaround for JDK-8159155
- && !"sun.tools.jconsole.OutputViewer".equals(name)) {
- UNSAFE.ensureClassInitialized(aClass);
- }
CompileTheWorld.OUT.printf("[%d]\t%s%n", id, name);
+ aClass = entry.loader().loadClass(name);
Compiler.compileClass(aClass, id, executor);
- } catch (ClassNotFoundException e) {
- CompileTheWorld.OUT.printf("Class %s loading failed : %s%n",
- name, e.getMessage());
+ } catch (Throwable e) {
+ CompileTheWorld.OUT.printf("[%d]\t%s\tWARNING skipped: %s%n",
+ id, name, e);
+ e.printStackTrace(CompileTheWorld.ERR);
}
}
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Tue Aug 08 21:16:00 2017 +0200
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Tue Aug 08 22:58:44 2017 +0200
@@ -217,4 +217,9 @@
return filename.substring(nameStart, filename.length() - CLASSFILE_EXT.length())
.replace(nameSeparator, '.');
}
+
+ public static String classNameToFileName(String classname) {
+ return classname.replace('.', '/')
+ .concat(CLASSFILE_EXT);
+ }
}