8207915: [AOT] jaotc w/ '--ignore-errors' should ignore illegal class files
authoriignatyev
Fri, 20 Jul 2018 11:39:37 -0700
changeset 51218 bfcdf06f97fa
parent 51217 79926aa725f7
child 51219 e5c3953c5f88
8207915: [AOT] jaotc w/ '--ignore-errors' should ignore illegal class files Reviewed-by: kvn
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java
test/hotspot/jtreg/compiler/aot/cli/jaotc/IgnoreErrorsTest.java
test/hotspot/jtreg/compiler/aot/cli/jaotc/IllegalClass.jasm
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java	Fri Jul 20 10:12:34 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Collector.java	Fri Jul 20 11:39:37 2018 -0700
@@ -61,7 +61,7 @@
 
         List<LoadedClass> foundClasses = null;
         try {
-            foundClasses = lookup.search(main.options.files, main.options.searchPath);
+            foundClasses = lookup.search(main.options.files, main.options.searchPath, this::handleLoadingError);
         } catch (InternalError e) {
             main.printer.reportError(e);
             return null;
@@ -118,12 +118,7 @@
                     addMethods(aotClass, ctors, compilationRestrictions);
                     total += ctors.length;
                 } catch (Throwable e) {
-                    // If we are running in JCK mode we ignore all exceptions.
-                    if (main.options.ignoreClassLoadingErrors) {
-                        main.printer.printError(c.getName() + ": " + e);
-                    } else {
-                        throw new InternalError(e);
-                    }
+                    handleLoadingError(c.getName(), e);
                 }
 
                 // Methods
@@ -132,12 +127,7 @@
                     addMethods(aotClass, methods, compilationRestrictions);
                     total += methods.length;
                 } catch (Throwable e) {
-                    // If we are running in JCK mode we ignore all exceptions.
-                    if (main.options.ignoreClassLoadingErrors) {
-                        main.printer.printError(c.getName() + ": " + e);
-                    } else {
-                        throw new InternalError(e);
-                    }
+                    handleLoadingError(c.getName(), e);
                 }
 
                 // Class initializer
@@ -148,12 +138,7 @@
                         total++;
                     }
                 } catch (Throwable e) {
-                    // If we are running in JCK mode we ignore all exceptions.
-                    if (main.options.ignoreClassLoadingErrors) {
-                        main.printer.printError(c.getName() + ": " + e);
-                    } else {
-                        throw new InternalError(e);
-                    }
+                    handleLoadingError(c.getName(), e);
                 }
 
                 // Found any methods to compile? Add the class.
@@ -215,4 +200,11 @@
         return compilationRestrictions;
     }
 
+    private void handleLoadingError(String name, Throwable t) {
+        if (main.options.ignoreClassLoadingErrors) {
+            main.printer.printError(name + ": " + t);
+        } else {
+            throw new InternalError(t);
+        }
+    }
 }
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java	Fri Jul 20 10:12:34 2018 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java	Fri Jul 20 11:39:37 2018 -0700
@@ -27,6 +27,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.BiConsumer;
 
 public final class ClassSearch {
     private final List<SourceProvider> providers = new ArrayList<>();
@@ -36,39 +37,53 @@
     }
 
     public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath) {
+        return search(search, searchPath, (s, t) -> { throw new InternalError(s + " : " + t, t); } );
+    }
+
+    public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath, BiConsumer<String, Throwable> classLoadingErrorsHandler) {
         List<LoadedClass> loaded = new ArrayList<>();
 
         List<ClassSource> sources = new ArrayList<>();
 
         for (SearchFor entry : search) {
-            sources.add(findSource(entry, searchPath));
+            sources.add(findSource(entry, searchPath, classLoadingErrorsHandler));
         }
 
         for (ClassSource source : sources) {
-            source.eachClass((name, loader) -> loaded.add(loadClass(name, loader)));
+            if (source != null) {
+                source.eachClass((name, loader) -> {
+                    LoadedClass x = loadClass(name, loader, classLoadingErrorsHandler);
+                    if (x != null) { loaded.add(x); }
+                });
+            }
         }
 
         return loaded;
     }
 
-    private static LoadedClass loadClass(String name, ClassLoader loader) {
+    private static LoadedClass loadClass(String name, ClassLoader loader, BiConsumer<String, Throwable> classLoadingErrorsHandler) {
         try {
             Class<?> clzz = loader.loadClass(name);
             return new LoadedClass(name, clzz);
-        } catch (ClassNotFoundException e) {
-            throw new InternalError("Failed to load with: " + loader, e);
+        } catch (Throwable e) {
+            classLoadingErrorsHandler.accept(name, e);
+            return null;
         }
     }
 
-    private ClassSource findSource(SearchFor searchFor, SearchPath searchPath) {
+    private ClassSource findSource(SearchFor searchFor, SearchPath searchPath, BiConsumer<String, Throwable> classLoadingErrorsHandler) {
         ClassSource found = null;
 
         for (SourceProvider provider : providers) {
             if (!searchFor.isUnknown() && !provider.supports(searchFor.getType())) {
                 continue;
             }
-
-            ClassSource source = provider.findSource(searchFor.getName(), searchPath);
+            ClassSource source = null;
+            try {
+                source = provider.findSource(searchFor.getName(), searchPath);
+            } catch (Throwable e) {
+                classLoadingErrorsHandler.accept(searchFor.getName(), e);
+            }
             if (source != null) {
                 if (found != null) {
                     throw new InternalError("Multiple possible sources: " + source + " and: " + found);
@@ -78,7 +93,7 @@
         }
 
         if (found == null) {
-            throw new InternalError("Failed to find " + searchFor.getType() + " file: " + searchFor.getName());
+            classLoadingErrorsHandler.accept(searchFor.getName(), new InternalError("Failed to find " + searchFor.getType() + " file: " + searchFor.getName()));
         }
         return found;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/IgnoreErrorsTest.java	Fri Jul 20 11:39:37 2018 -0700
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @requires vm.aot
+ * @library / /test/lib /testlibrary
+ * @compile IllegalClass.jasm
+ * @run driver compiler.aot.cli.jaotc.IgnoreErrorsTest
+ */
+
+package compiler.aot.cli.jaotc;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class IgnoreErrorsTest {
+    public static void main(String[] args) {
+        try {
+            Files.write(Paths.get("Empty.class"), new byte[] { }, StandardOpenOption.CREATE_NEW);
+        } catch (IOException e) {
+            throw new Error("can't create empty class file", e);
+        }
+        File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
+        OutputAnalyzer oa;
+
+        System.out.println("Compiling empty class file w/o --ignore-errors");
+        oa = JaotcTestHelper.compileLibrary(
+            "--class-name", "Empty",
+            "--class-name", "java.lang.Object");
+        oa.shouldNotHaveExitValue(0);
+        Asserts.assertTrue(!compiledLibrary.exists(), "Compiled library file exists");
+
+        System.out.println("Compiling empty class file w/ --ignore-errors");
+        oa = JaotcTestHelper.compileLibrary(
+            "--ignore-errors",
+            "--class-name", "Empty",
+            "--class-name", "java.lang.Object");
+        oa.shouldHaveExitValue(0);
+        Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file is missed");
+        JaotcTestHelper.checkLibraryUsage("-version");
+        compiledLibrary.delete();
+
+        System.out.println("Compiling illegal class file w/o --ignore-errors");
+        oa = JaotcTestHelper.compileLibrary(
+            "--class-name", "IllegalClass",
+            "--class-name", "java.lang.Object");
+        oa.shouldNotHaveExitValue(0);
+        Asserts.assertTrue(!compiledLibrary.exists(), "Compiled library file exists");
+
+        System.out.println("Compiling illegal class file w/ --ignore-errors");
+        oa = JaotcTestHelper.compileLibrary(
+            "--ignore-errors",
+            "--class-name", "IllegalClass",
+            "--class-name", "java.lang.Object");
+        oa.shouldHaveExitValue(0);
+        Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file is missed");
+        JaotcTestHelper.checkLibraryUsage("-version");
+        compiledLibrary.delete();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/IllegalClass.jasm	Fri Jul 20 11:39:37 2018 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+super public class IllegalClass
+    extends java/lang/String
+    version 46:0
+{ }