Skip to content

Commit

Permalink
Use JRTFS instead of initializing a FileManager to process --system
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 565773578
Change-Id: I1c8a803d1650d8c0beb9a6bf074b53369144e1df
  • Loading branch information
cushon authored and copybara-github committed Sep 15, 2023
1 parent d20ae04 commit 325a9e1
Showing 1 changed file with 35 additions and 53 deletions.
88 changes: 35 additions & 53 deletions toolchains/DumpPlatformClassPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.util.Context;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
Expand All @@ -38,11 +42,6 @@
import java.util.jar.JarOutputStream;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;

/**
* Output a jar file containing all classes on the platform classpath of the given JDK release.
Expand Down Expand Up @@ -98,50 +97,35 @@ static boolean dumpJDK9AndNewerBootClassPath(
return true;
}

// Initialize a FileManager to process the --system argument, and then read the
// initialized bootclasspath data back out.

Context context = new Context();
try {
JavacTool.create()
.getTask(
/* out = */ null,
/* fileManager = */ null,
/* diagnosticListener = */ null,
/* options = */ Arrays.asList("--system", String.valueOf(targetJavabase)),
/* classes = */ null,
/* compilationUnits = */ null,
context);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
String.format(
"Failed to collect system class path. Please ensure that the configured Java runtime"
+ " ('%s') is a complete JDK. There are known issues with Homebrew versions of"
+ " the Java runtime.",
targetJavabase.toRealPath()),
e);
}
StandardJavaFileManager fileManager =
(StandardJavaFileManager) context.get(JavaFileManager.class);

SortedMap<String, InputStream> entries = new TreeMap<>();
for (JavaFileObject fileObject :
fileManager.list(
StandardLocation.PLATFORM_CLASS_PATH,
"",
EnumSet.of(Kind.CLASS),
/* recurse= */ true)) {
String binaryName =
fileManager.inferBinaryName(StandardLocation.PLATFORM_CLASS_PATH, fileObject);
entries.put(binaryName.replace('.', '/') + ".class", fileObject.openInputStream());
// Read the bootclasspath data using the JRT filesystem
Map<String, byte[]> entries = new TreeMap<>();
Map<String, String> env = new TreeMap<>();
env.put("java.home", String.valueOf(targetJavabase));
try (FileSystem fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), env)) {
Path modules = fileSystem.getPath("/modules");
try (DirectoryStream<Path> ms = Files.newDirectoryStream(modules)) {
for (Path m : ms) {
Files.walkFileTree(
m,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
if (file.getFileName().toString().endsWith(".class")) {
entries.put(m.relativize(file).toString(), Files.readAllBytes(file));
}
return super.visitFile(file, attrs);
}
});
}
}
writeEntries(output, entries);
}
writeEntries(output, entries);
return true;
}

/** Writes the given entry names and data to a jar archive at the given path. */
private static void writeEntries(Path output, Map<String, InputStream> entries)
throws IOException {
private static void writeEntries(Path output, Map<String, byte[]> entries) throws IOException {
if (!entries.containsKey("java/lang/Object.class")) {
throw new AssertionError(
"\nCould not find java.lang.Object on bootclasspath; something has gone terribly wrong.\n"
Expand All @@ -168,14 +152,14 @@ private static void writeClassPathJars(Path output, Collection<Path> paths) thro
for (Path path : paths) {
jars.add(new JarFile(path.toFile()));
}
SortedMap<String, InputStream> entries = new TreeMap<>();
SortedMap<String, byte[]> entries = new TreeMap<>();
for (JarFile jar : jars) {
jar.stream()
.filter(p -> p.getName().endsWith(".class"))
.forEachOrdered(
entry -> {
try {
entries.put(entry.getName(), jar.getInputStream(entry));
entries.put(entry.getName(), toByteArray(jar.getInputStream(entry)));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down Expand Up @@ -214,12 +198,10 @@ private static List<Path> getBootClassPathJars(Path javaHome) throws IOException
* Add a jar entry to the given {@link JarOutputStream}, normalizing the entry timestamps to
* ensure deterministic build output.
*/
private static void addEntry(JarOutputStream jos, String name, InputStream input)
throws IOException {
private static void addEntry(JarOutputStream jos, String name, byte[] bytes) throws IOException {
JarEntry je = new JarEntry(name);
je.setTime(FIXED_TIMESTAMP);
je.setMethod(ZipEntry.STORED);
byte[] bytes = toByteArray(input);
// When targeting JDK >= 10, patch the major version so it will be accepted by javac 9
// TODO(cushon): remove this after updating javac
if (bytes[7] > 53) {
Expand Down Expand Up @@ -266,4 +248,4 @@ static int hostMajorVersion() {
throw new IllegalStateException(
"Unknown Java version: " + System.getProperty("java.specification.version"));
}
}
}

0 comments on commit 325a9e1

Please sign in to comment.