8353840: JNativeScan should not abort for missing classes
Reviewed-by: jvernee, liach
This commit is contained in:
parent
1f21da75eb
commit
5f2a604b63
@ -42,15 +42,17 @@ import java.util.zip.ZipFile;
|
||||
class JNativeScanTask {
|
||||
|
||||
private final PrintWriter out;
|
||||
private final PrintWriter err;
|
||||
private final List<Path> classPaths;
|
||||
private final List<Path> modulePaths;
|
||||
private final List<String> cmdRootModules;
|
||||
private final Runtime.Version version;
|
||||
private final Action action;
|
||||
|
||||
public JNativeScanTask(PrintWriter out, List<Path> classPaths, List<Path> modulePaths,
|
||||
public JNativeScanTask(PrintWriter out, PrintWriter err, List<Path> classPaths, List<Path> modulePaths,
|
||||
List<String> cmdRootModules, Runtime.Version version, Action action) {
|
||||
this.out = out;
|
||||
this.err = err;
|
||||
this.classPaths = classPaths;
|
||||
this.modulePaths = modulePaths;
|
||||
this.version = version;
|
||||
@ -71,10 +73,13 @@ class JNativeScanTask {
|
||||
toScan.add(new ClassFileSource.Module(m.reference()));
|
||||
}
|
||||
|
||||
Set<String> errors = new LinkedHashSet<>();
|
||||
Diagnostics diagnostics = (context, error) ->
|
||||
errors.add("Error while processing method: " + context + ": " + error.getMessage());
|
||||
SortedMap<ClassFileSource, SortedMap<ClassDesc, List<RestrictedUse>>> allRestrictedMethods;
|
||||
try(ClassResolver classesToScan = ClassResolver.forClassFileSources(toScan, version);
|
||||
ClassResolver systemClassResolver = ClassResolver.forSystemModules(version)) {
|
||||
NativeMethodFinder finder = NativeMethodFinder.create(classesToScan, systemClassResolver);
|
||||
NativeMethodFinder finder = NativeMethodFinder.create(diagnostics, classesToScan, systemClassResolver);
|
||||
allRestrictedMethods = finder.findAll();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -82,7 +87,7 @@ class JNativeScanTask {
|
||||
|
||||
switch (action) {
|
||||
case PRINT -> printNativeAccess(allRestrictedMethods);
|
||||
case DUMP_ALL -> dumpAll(allRestrictedMethods);
|
||||
case DUMP_ALL -> dumpAll(allRestrictedMethods, errors);
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,7 +161,7 @@ class JNativeScanTask {
|
||||
out.println(nativeAccess);
|
||||
}
|
||||
|
||||
private void dumpAll(SortedMap<ClassFileSource, SortedMap<ClassDesc, List<RestrictedUse>>> allRestrictedMethods) {
|
||||
private void dumpAll(SortedMap<ClassFileSource, SortedMap<ClassDesc, List<RestrictedUse>>> allRestrictedMethods, Set<String> errors) {
|
||||
if (allRestrictedMethods.isEmpty()) {
|
||||
out.println(" <no restricted methods>");
|
||||
} else {
|
||||
@ -177,6 +182,10 @@ class JNativeScanTask {
|
||||
});
|
||||
});
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
err.println("Error(s) while processing classes:");
|
||||
errors.forEach(error -> err.println(" " + error));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isJarFile(Path path) throws JNativeScanFatalError {
|
||||
@ -192,4 +201,8 @@ class JNativeScanTask {
|
||||
String packagePrefix = desc.packageName().isEmpty() ? "" : desc.packageName() + ".";
|
||||
return packagePrefix + desc.displayName();
|
||||
}
|
||||
|
||||
interface Diagnostics {
|
||||
void error(MethodRef context, JNativeScanFatalError error);
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ public class Main {
|
||||
action = JNativeScanTask.Action.PRINT;
|
||||
}
|
||||
|
||||
new JNativeScanTask(out, classPathJars, modulePaths, rootModules, version, action).run();
|
||||
new JNativeScanTask(out, err, classPathJars, modulePaths, rootModules, version, action).run();
|
||||
}
|
||||
|
||||
private static String[] expandArgFiles(String[] args) throws JNativeScanFatalError {
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
package com.sun.tools.jnativescan;
|
||||
|
||||
import com.sun.tools.jnativescan.JNativeScanTask.Diagnostics;
|
||||
import com.sun.tools.jnativescan.RestrictedUse.NativeMethodDecl;
|
||||
import com.sun.tools.jnativescan.RestrictedUse.RestrictedMethodRefs;
|
||||
|
||||
@ -44,16 +45,19 @@ class NativeMethodFinder {
|
||||
private static final String RESTRICTED_NAME = "Ljdk/internal/javac/Restricted+Annotation;";
|
||||
|
||||
private final Map<MethodRef, Boolean> cache = new HashMap<>();
|
||||
private final Diagnostics diagnostics;
|
||||
private final ClassResolver classesToScan;
|
||||
private final ClassResolver systemClassResolver;
|
||||
|
||||
private NativeMethodFinder(ClassResolver classesToScan, ClassResolver systemClassResolver) {
|
||||
private NativeMethodFinder(Diagnostics diagnostics, ClassResolver classesToScan, ClassResolver systemClassResolver) {
|
||||
this.diagnostics = diagnostics;
|
||||
this.classesToScan = classesToScan;
|
||||
this.systemClassResolver = systemClassResolver;
|
||||
}
|
||||
|
||||
public static NativeMethodFinder create(ClassResolver classesToScan, ClassResolver systemClassResolver) throws JNativeScanFatalError, IOException {
|
||||
return new NativeMethodFinder(classesToScan, systemClassResolver);
|
||||
public static NativeMethodFinder create(Diagnostics diagnostics, ClassResolver classesToScan,
|
||||
ClassResolver systemClassResolver) throws JNativeScanFatalError, IOException {
|
||||
return new NativeMethodFinder(diagnostics, classesToScan, systemClassResolver);
|
||||
}
|
||||
|
||||
public SortedMap<ClassFileSource, SortedMap<ClassDesc, List<RestrictedUse>>> findAll() throws JNativeScanFatalError {
|
||||
@ -68,23 +72,22 @@ class NativeMethodFinder {
|
||||
} else {
|
||||
SortedSet<MethodRef> perMethod = new TreeSet<>(Comparator.comparing(MethodRef::toString));
|
||||
methodModel.code().ifPresent(code -> {
|
||||
try {
|
||||
code.forEach(e -> {
|
||||
switch (e) {
|
||||
case InvokeInstruction invoke -> {
|
||||
MethodRef ref = MethodRef.ofInvokeInstruction(invoke);
|
||||
try {
|
||||
if (isRestrictedMethod(ref)) {
|
||||
perMethod.add(ref);
|
||||
}
|
||||
} catch (JNativeScanFatalError ex) {
|
||||
diagnostics.error(MethodRef.ofModel(methodModel), ex);
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (JNativeScanFatalError e) {
|
||||
throw new JNativeScanFatalError("Error while processing method: " +
|
||||
MethodRef.ofModel(methodModel), e);
|
||||
}
|
||||
});
|
||||
if (!perMethod.isEmpty()) {
|
||||
perClass.add(new RestrictedMethodRefs(MethodRef.ofModel(methodModel), perMethod));
|
||||
|
@ -35,6 +35,9 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TestMissingSystemClass extends JNativeScanTestBase {
|
||||
|
||||
@ -49,12 +52,15 @@ public class TestMissingSystemClass extends JNativeScanTestBase {
|
||||
|
||||
@Test
|
||||
public void testSingleJarClassPath() {
|
||||
assertFailure(jnativescan("--class-path", MISSING_SYSTEM.toString(), "--release", "21"))
|
||||
.stdoutShouldBeEmpty()
|
||||
List<String> stderr = assertSuccess(jnativescan("--class-path", MISSING_SYSTEM.toString(), "--release", "21"))
|
||||
.stdoutShouldContain("<no restricted methods>")
|
||||
.stderrShouldContain("Error(s) while processing classes")
|
||||
.stderrShouldContain("Error while processing method")
|
||||
.stderrShouldContain("missingsystem.App::main(String[])void")
|
||||
.stderrShouldContain("CAUSED BY:")
|
||||
.stderrShouldContain("System class can not be found")
|
||||
.stderrShouldContain("java.lang.Compiler");
|
||||
.stderrShouldContain("java.lang.Compiler")
|
||||
.stderrAsLines();
|
||||
|
||||
assertEquals(2, stderr.size(), "Unexpected number of lines in stderr");
|
||||
}
|
||||
}
|
||||
|
@ -28,5 +28,6 @@ public class App {
|
||||
// if we compile with --release 20, but run jnativescan
|
||||
// with --release 21, we should get an error
|
||||
java.lang.Compiler.enable();
|
||||
java.lang.Compiler.enable(); // should be de-duplicated in the error logs
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user