提交 9e1b748e 编写于 作者: A andrew

8189762: [TESTBUG] Create tests for JDK-8146115 container awareness and resource configuration

Summary: Sync ClassFileInstaller.java with the HotSpot version
Reviewed-by: phh
上级 9f1e818d
/* /*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -21,28 +21,229 @@ ...@@ -21,28 +21,229 @@
* questions. * questions.
*/ */
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream; import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/** /**
* Dump a class file for a class on the class path in the current directory * Dump a class file for a class on the class path in the current directory, or
* in the specified JAR file. This class is usually used when you build a class
* from a test library, but want to use this class in a sub-process.
*
* For example, to build the following library class:
* test/lib/sun/hotspot/WhiteBox.java
*
* You would use the following tags:
*
* @library /test/lib
* @build sun.hotspot.WhiteBox
*
* JTREG would build the class file under
* ${JTWork}/classes/test/lib/sun/hotspot/WhiteBox.class
*
* With you run your main test class using "@run main MyMainClass", JTREG would setup the
* -classpath to include "${JTWork}/classes/test/lib/", so MyMainClass would be able to
* load the WhiteBox class.
*
* However, if you run a sub process, and do not wish to use the exact same -classpath,
* You can use ClassFileInstaller to ensure that WhiteBox is available in the current
* directory of your test:
*
* @run main ClassFileInstaller sun.hotspot.WhiteBox
*
* Or, you can use the -jar option to store the class in the specified JAR file. If a relative
* path name is given, the JAR file would be relative to the current directory of
*
* @run main ClassFileInstaller -jar myjar.jar sun.hotspot.WhiteBox
*/ */
public class ClassFileInstaller { public class ClassFileInstaller {
/**
* You can enable debug tracing of ClassFileInstaller by running JTREG with
* jtreg -DClassFileInstaller.debug=true ... <names of tests>
*/
public static boolean DEBUG = Boolean.getBoolean("ClassFileInstaller.debug");
/** /**
* @param args The names of the classes to dump * @param args The names of the classes to dump
* @throws Exception * @throws Exception
*/ */
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {
for (String arg : args) { if (args.length > 1 && args[0].equals("-jar")) {
ClassLoader cl = ClassFileInstaller.class.getClassLoader(); if (args.length < 2) {
throw new RuntimeException("Usage: ClassFileInstaller <options> <classes>\n" +
"where possible options include:\n" +
" -jar <path> Write to the JAR file <path>");
}
writeJar(args[1], null, args, 2, args.length);
} else {
if (DEBUG) {
System.out.println("ClassFileInstaller: Writing to " + System.getProperty("user.dir"));
}
for (String arg : args) {
writeClassToDisk(arg);
}
}
}
public static class Manifest {
private InputStream in;
private Manifest(InputStream in) {
this.in = in;
}
static Manifest fromSourceFile(String fileName) throws Exception {
String pathName = System.getProperty("test.src") + File.separator + fileName;
return new Manifest(new FileInputStream(pathName));
}
// Example:
// String manifest = "Premain-Class: RedefineClassHelper\n" +
// "Can-Redefine-Classes: true\n";
// ClassFileInstaller.writeJar("redefineagent.jar",
// ClassFileInstaller.Manifest.fromString(manifest),
// "RedefineClassHelper");
static Manifest fromString(String manifest) throws Exception {
return new Manifest(new ByteArrayInputStream(manifest.getBytes()));
}
public InputStream getInputStream() {
return in;
}
}
private static void writeJar(String jarFile, Manifest manifest, String classes[], int from, int to) throws Exception {
if (DEBUG) {
System.out.println("ClassFileInstaller: Writing to " + getJarPath(jarFile));
}
(new File(jarFile)).delete();
FileOutputStream fos = new FileOutputStream(jarFile);
ZipOutputStream zos = new ZipOutputStream(fos);
// The manifest must be the first or second entry. See comments in JarInputStream
// constructor and JDK-5046178.
if (manifest != null) {
writeToDisk(zos, "META-INF/MANIFEST.MF", manifest.getInputStream());
}
for (int i=from; i<to; i++) {
writeClassToDisk(zos, classes[i]);
}
zos.close();
fos.close();
}
/*
* You can call ClassFileInstaller.writeJar() from your main test class instead of
* using "@run ClassFileInstaller -jar ...". E.g.,
*
* String jarPath = ClassFileInstaller.getJarPath("myjar.jar", "sun.hotspot.WhiteBox")
*
* If you call this API, make sure you build ClassFileInstaller with the following tags:
*
* @library testlibrary
* @build ClassFileInstaller
*/
public static String writeJar(String jarFile, String... classes) throws Exception {
writeJar(jarFile, null, classes, 0, classes.length);
return getJarPath(jarFile);
}
// Convert dotted class name to a path to a class file public static String writeJar(String jarFile, Manifest manifest, String... classes) throws Exception {
String pathName = arg.replace('.', '/').concat(".class"); writeJar(jarFile, manifest, classes, 0, classes.length);
InputStream is = cl.getResourceAsStream(pathName); return getJarPath(jarFile);
}
/**
* This returns the absolute path to the file specified in "@ClassFileInstaller -jar myjar.jar",
* In your test program, instead of using the JAR file name directly:
*
* String jarPath = "myjar.jar";
*
* you should call this function, like:
*
* String jarPath = ClassFileInstaller.getJarPath("myjar.jar")
*
* The reasons are:
* (1) Using absolute path makes it easy to cut-and-paste from the JTR file and rerun your
* test in any directory.
* (2) In the future, we may make the JAR file name unique to avoid clobbering
* during parallel JTREG execution.
*
*/
public static String getJarPath(String jarFileName) {
return new File(jarFileName).getAbsolutePath();
}
public static void writeClassToDisk(String className) throws Exception {
writeClassToDisk((ZipOutputStream)null, className);
}
private static void writeClassToDisk(ZipOutputStream zos, String className) throws Exception {
writeClassToDisk(zos, className, "");
}
public static void writeClassToDisk(String className, String prependPath) throws Exception {
writeClassToDisk(null, className, prependPath);
}
private static void writeClassToDisk(ZipOutputStream zos, String className, String prependPath) throws Exception {
ClassLoader cl = ClassFileInstaller.class.getClassLoader();
// Convert dotted class name to a path to a class file
String pathName = className.replace('.', '/').concat(".class");
InputStream is = cl.getResourceAsStream(pathName);
if (is == null) {
throw new RuntimeException("Failed to find " + pathName);
}
if (prependPath.length() > 0) {
pathName = prependPath + "/" + pathName;
}
writeToDisk(zos, pathName, is);
}
public static void writeClassToDisk(String className, byte[] bytecode) throws Exception {
writeClassToDisk(null, className, bytecode);
}
private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode) throws Exception {
writeClassToDisk(zos, className, bytecode, "");
}
public static void writeClassToDisk(String className, byte[] bytecode, String prependPath) throws Exception {
writeClassToDisk(null, className, bytecode, prependPath);
}
private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode, String prependPath) throws Exception {
// Convert dotted class name to a path to a class file
String pathName = className.replace('.', '/').concat(".class");
if (prependPath.length() > 0) {
pathName = prependPath + "/" + pathName;
}
writeToDisk(zos, pathName, new ByteArrayInputStream(bytecode));
}
private static void writeToDisk(ZipOutputStream zos, String pathName, InputStream is) throws Exception {
if (DEBUG) {
System.out.println("ClassFileInstaller: Writing " + pathName);
}
if (zos != null) {
ZipEntry ze = new ZipEntry(pathName);
zos.putNextEntry(ze);
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf))>0){
zos.write(buf, 0, len);
}
} else {
// Create the class file's package directory // Create the class file's package directory
Path p = Paths.get(pathName); Path p = Paths.get(pathName);
Path parent = p.getParent(); Path parent = p.getParent();
...@@ -52,5 +253,6 @@ public class ClassFileInstaller { ...@@ -52,5 +253,6 @@ public class ClassFileInstaller {
// Create the class file // Create the class file
Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
} }
is.close();
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册