mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-07 00:48:38 +00:00
8160398: (jdeps) Replace a list of JDK 8 internal API for detecting if it's removed in JDK 9 or later
Reviewed-by: dfuchs
This commit is contained in:
parent
e08b3b12fb
commit
de4f424b8c
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 build.tools.listjdkinternals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Run this tool to generate the JDK internal APIs in the previous releases
|
||||
* including platform-specific internal APIs.
|
||||
*/
|
||||
public class ListJDKInternals {
|
||||
// Filter non-interesting JAR files
|
||||
private final static List<String> excludes = Arrays.asList(
|
||||
"deploy.jar",
|
||||
"javaws.jar",
|
||||
"plugin.jar",
|
||||
"cldrdata.jar",
|
||||
"localedata.jar"
|
||||
);
|
||||
private static void usage() {
|
||||
System.out.println("ListJDKInternals [-o <outfile>] <javaHome> [<javaHome>]*");
|
||||
}
|
||||
|
||||
private static final Set<String> EXPORTED_PACKAGES = new HashSet<>();
|
||||
|
||||
public static void main(String... args) throws IOException {
|
||||
List<Path> paths = new ArrayList<>();
|
||||
Path outFile = null;
|
||||
int i=0;
|
||||
while (i < args.length) {
|
||||
String arg = args[i++];
|
||||
if (arg.equals("-o")) {
|
||||
outFile = Paths.get(args[i++]);
|
||||
} else {
|
||||
Path p = Paths.get(arg);
|
||||
if (Files.notExists(p))
|
||||
throw new IllegalArgumentException(p + " not exist");
|
||||
paths.add(p);
|
||||
}
|
||||
}
|
||||
if (paths.isEmpty()) {
|
||||
usage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Get the exported APIs from the current JDK releases
|
||||
Path javaHome = Paths.get(System.getProperty("java.home"));
|
||||
ModuleFinder.ofSystem().findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.filter(md -> !md.name().equals("jdk.unsupported"))
|
||||
.map(ModuleDescriptor::exports)
|
||||
.flatMap(Set::stream)
|
||||
.filter(exp -> !exp.isQualified())
|
||||
.map(ModuleDescriptor.Exports::source)
|
||||
.forEach(EXPORTED_PACKAGES::add);
|
||||
|
||||
ListJDKInternals listJDKInternals = new ListJDKInternals(paths);
|
||||
if (outFile != null) {
|
||||
try (OutputStream out = Files.newOutputStream(outFile);
|
||||
PrintStream pw = new PrintStream(out)) {
|
||||
listJDKInternals.write(pw);
|
||||
}
|
||||
} else {
|
||||
listJDKInternals.write(System.out);
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<String> packages = new HashSet<>();
|
||||
ListJDKInternals(List<Path> dirs) throws IOException {
|
||||
for (Path p : dirs) {
|
||||
packages.addAll(list(p));
|
||||
}
|
||||
}
|
||||
|
||||
private void write(PrintStream pw) {
|
||||
pw.println("# This file is auto-generated by ListJDKInternals tool on " +
|
||||
LocalDateTime.now().toString());
|
||||
packages.stream().sorted()
|
||||
.forEach(pw::println);
|
||||
}
|
||||
|
||||
private Set<String> list(Path javaHome) throws IOException {
|
||||
Path jrt = javaHome.resolve("lib").resolve("modules");
|
||||
Path jre = javaHome.resolve("jre");
|
||||
|
||||
if (Files.exists(jrt)) {
|
||||
return listModularRuntime(javaHome);
|
||||
} else if (Files.exists(jre.resolve("lib").resolve("rt.jar"))) {
|
||||
return listLegacyRuntime(javaHome);
|
||||
}
|
||||
throw new IllegalArgumentException("invalid " + javaHome);
|
||||
}
|
||||
|
||||
private Set<String> listModularRuntime(Path javaHome) throws IOException {
|
||||
Map<String, String> env = new HashMap<>();
|
||||
env.put("java.home", javaHome.toString());
|
||||
FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), env);
|
||||
Path root = fs.getPath("packages");
|
||||
return Files.walk(root, 1)
|
||||
.map(Path::getFileName)
|
||||
.map(Path::toString)
|
||||
.filter(pn -> !EXPORTED_PACKAGES.contains(pn))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private Set<String> listLegacyRuntime(Path javaHome) throws IOException {
|
||||
List<Path> dirs = new ArrayList<>();
|
||||
Path jre = javaHome.resolve("jre");
|
||||
Path lib = javaHome.resolve("lib");
|
||||
|
||||
dirs.add(jre.resolve("lib"));
|
||||
dirs.add(jre.resolve("lib").resolve("ext"));
|
||||
dirs.add(lib.resolve("tools.jar"));
|
||||
dirs.add(lib.resolve("jconsole.jar"));
|
||||
Set<String> packages = new HashSet<>();
|
||||
for (Path d : dirs) {
|
||||
Files.find(d, 1, (Path p, BasicFileAttributes attr)
|
||||
-> p.getFileName().toString().endsWith(".jar") &&
|
||||
!excludes.contains(p.getFileName().toString()))
|
||||
.map(ListJDKInternals::walkJarFile)
|
||||
.flatMap(Set::stream)
|
||||
.filter(pn -> !EXPORTED_PACKAGES.contains(pn))
|
||||
.forEach(packages::add);
|
||||
}
|
||||
return packages;
|
||||
}
|
||||
|
||||
static Set<String> walkJarFile(Path jarfile) {
|
||||
try (JarFile jf = new JarFile(jarfile.toFile())) {
|
||||
return jf.stream()
|
||||
.map(JarEntry::getName)
|
||||
.filter(n -> n.endsWith(".class"))
|
||||
.map(ListJDKInternals::toPackage)
|
||||
.collect(Collectors.toSet());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static String toPackage(String name) {
|
||||
int i = name.lastIndexOf('/');
|
||||
if (i < 0) {
|
||||
System.err.format("Warning: unnamed package %s%n", name);
|
||||
}
|
||||
return i >= 0 ? name.substring(0, i).replace("/", ".") : "";
|
||||
}
|
||||
}
|
||||
@ -25,20 +25,19 @@
|
||||
|
||||
package com.sun.tools.jdeps;
|
||||
|
||||
import static com.sun.tools.jdeps.JdepsConfiguration.*;
|
||||
|
||||
import com.sun.tools.classfile.Dependency.Location;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -369,35 +368,29 @@ public class Analyzer {
|
||||
}
|
||||
}
|
||||
|
||||
static final JdkInternals REMOVED_JDK_INTERNALS = new JdkInternals();
|
||||
static final Jdk8Internals REMOVED_JDK_INTERNALS = new Jdk8Internals();
|
||||
|
||||
static class JdkInternals extends Module {
|
||||
private final String BUNDLE = "com.sun.tools.jdeps.resources.jdkinternals";
|
||||
|
||||
private final Set<String> jdkinternals;
|
||||
private final Set<String> jdkUnsupportedClasses;
|
||||
private JdkInternals() {
|
||||
static class Jdk8Internals extends Module {
|
||||
private final String JDK8_INTERNALS = "/com/sun/tools/jdeps/resources/jdk8_internals.txt";
|
||||
private final Set<String> jdk8Internals;
|
||||
private Jdk8Internals() {
|
||||
super("JDK removed internal API");
|
||||
|
||||
try {
|
||||
ResourceBundle rb = ResourceBundle.getBundle(BUNDLE);
|
||||
this.jdkinternals = rb.keySet();
|
||||
} catch (MissingResourceException e) {
|
||||
throw new InternalError("Cannot find jdkinternals resource bundle");
|
||||
try (InputStream in = JdepsTask.class.getResourceAsStream(JDK8_INTERNALS);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
|
||||
this.jdk8Internals = reader.lines()
|
||||
.filter(ln -> !ln.startsWith("#"))
|
||||
.collect(Collectors.toSet());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
||||
this.jdkUnsupportedClasses = getUnsupportedClasses();
|
||||
}
|
||||
|
||||
public boolean contains(Location location) {
|
||||
if (jdkUnsupportedClasses.contains(location.getName() + ".class")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String cn = location.getClassName();
|
||||
int i = cn.lastIndexOf('.');
|
||||
String pn = i > 0 ? cn.substring(0, i) : "";
|
||||
return jdkinternals.contains(cn) || jdkinternals.contains(pn);
|
||||
|
||||
return jdk8Internals.contains(pn);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -414,25 +407,5 @@ public class Analyzer {
|
||||
public boolean isExported(String pn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private Set<String> getUnsupportedClasses() {
|
||||
// jdk.unsupported may not be observable
|
||||
Optional<Module> om = Profile.FULL_JRE.findModule(JDK_UNSUPPORTED);
|
||||
if (om.isPresent()) {
|
||||
return om.get().reader().entries();
|
||||
}
|
||||
|
||||
// find from local run-time image
|
||||
SystemModuleFinder system = new SystemModuleFinder();
|
||||
if (system.find(JDK_UNSUPPORTED).isPresent()) {
|
||||
try {
|
||||
return system.getClassReader(JDK_UNSUPPORTED).entries();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ sun.security.util.SecurityConstants=Use appropriate java.security.Permission sub
|
||||
sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4
|
||||
sun.tools.jar=Use java.util.jar or jar tool @since 1.2
|
||||
# Internal APIs removed in JDK 9
|
||||
com.apple.eawt=Use java.awt.desktop and JEP 272 @since 9
|
||||
com.apple.eawt=Use java.awt.Desktop and JEP 272 @since 9
|
||||
com.apple.concurrent=Removed. See https://bugs.openjdk.java.net/browse/JDK-8148187
|
||||
com.sun.image.codec.jpeg=Use javax.imageio @since 1.4
|
||||
sun.awt.image.codec=Use javax.imageio @since 1.4
|
||||
|
||||
@ -71,7 +71,7 @@ public class RemovedJDKInternals {
|
||||
assertTrue(CompilerUtils.compile(codecSrc, codecDest));
|
||||
|
||||
// patch jdk.unsupported and set -cp to codec types
|
||||
assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src"),
|
||||
assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "p"),
|
||||
CLASSES_DIR,
|
||||
"-Xpatch:jdk.unsupported=" + patchDir,
|
||||
"-cp", codecDest.toString()));
|
||||
|
||||
@ -59,14 +59,17 @@ public class ShowReplacement {
|
||||
public void compileAll() throws Exception {
|
||||
CompilerUtils.cleanDir(CLASSES_DIR);
|
||||
|
||||
assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "p"),
|
||||
Path tmp = Paths.get("tmp");
|
||||
assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "apple"), tmp));
|
||||
assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "q"),
|
||||
CLASSES_DIR,
|
||||
"-cp", tmp.toString(),
|
||||
"-XaddExports:java.base/sun.security.util=ALL-UNNAMED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withReplacement() {
|
||||
Path file = Paths.get("p", "WithRepl.class");
|
||||
Path file = Paths.get("q", "WithRepl.class");
|
||||
String[] output = JdepsUtil.jdeps("-jdkinternals", CLASSES_DIR.resolve(file).toString());
|
||||
int i = 0;
|
||||
while (!output[i].contains("Suggested Replacement")) {
|
||||
@ -90,9 +93,29 @@ public class ShowReplacement {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A JDK internal class has been removed while its package still exists.
|
||||
*/
|
||||
@Test
|
||||
public void noReplacement() {
|
||||
Path file = Paths.get("p", "NoRepl.class");
|
||||
Path file = Paths.get("q", "NoRepl.class");
|
||||
String[] output = JdepsUtil.jdeps("-jdkinternals", CLASSES_DIR.resolve(file).toString());
|
||||
int i = 0;
|
||||
// expect no replacement
|
||||
while (i < output.length && !output[i].contains("Suggested Replacement")) {
|
||||
i++;
|
||||
}
|
||||
|
||||
// no replacement
|
||||
assertEquals(output.length-i, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* A JDK internal package has been removed.
|
||||
*/
|
||||
@Test
|
||||
public void removedPackage() {
|
||||
Path file = Paths.get("q", "RemovedPackage.class");
|
||||
String[] output = JdepsUtil.jdeps("-jdkinternals", CLASSES_DIR.resolve(file).toString());
|
||||
int i = 0;
|
||||
// expect no replacement
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 apple.applescript;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
|
||||
public interface AppleScriptEngine extends ScriptEngine {
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package p;
|
||||
package q;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 q;
|
||||
|
||||
import apple.applescript.AppleScriptEngine;
|
||||
|
||||
public class RemovedPackage {
|
||||
AppleScriptEngine scriptEngine;
|
||||
}
|
||||
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package p;
|
||||
package q;
|
||||
|
||||
import sun.security.util.HostnameChecker;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user