8153391: an image created for \"jdk.compiler\" fails to run javac

Improving errors produced by javac when the zipfs implementation is missing in the JDK image.

Reviewed-by: jjg
This commit is contained in:
Jan Lahoda 2016-08-22 09:59:43 +02:00
parent 9f44318ef9
commit 53cd7b54fa
8 changed files with 192 additions and 41 deletions

View file

@ -29,7 +29,7 @@ import java.io.IOException;
import java.nio.file.FileSystems; import java.nio.file.FileSystems;
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.spi.FileSystemProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -118,4 +118,19 @@ public class FSInfo {
return list; return list;
} }
} }
private FileSystemProvider jarFSProvider;
public synchronized FileSystemProvider getJarFSProvider() {
if (jarFSProvider != null) {
return jarFSProvider;
}
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
if (provider.getScheme().equals("jar")) {
return (jarFSProvider = provider);
}
}
return null;
}
} }

View file

@ -69,6 +69,7 @@ import javax.tools.StandardJavaFileManager;
import com.sun.tools.javac.file.RelativePath.RelativeDirectory; import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
import com.sun.tools.javac.file.RelativePath.RelativeFile; import com.sun.tools.javac.file.RelativePath.RelativeFile;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api; import com.sun.tools.javac.util.DefinedBy.Api;
@ -509,7 +510,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
this.archivePath = archivePath; this.archivePath = archivePath;
if (multiReleaseValue != null && archivePath.toString().endsWith(".jar")) { if (multiReleaseValue != null && archivePath.toString().endsWith(".jar")) {
Map<String,String> env = Collections.singletonMap("multi-release", multiReleaseValue); Map<String,String> env = Collections.singletonMap("multi-release", multiReleaseValue);
this.fileSystem = getJarFSProvider().newFileSystem(archivePath, env); FileSystemProvider jarFSProvider = fsInfo.getJarFSProvider();
Assert.checkNonNull(jarFSProvider, "should have been caught before!");
this.fileSystem = jarFSProvider.newFileSystem(archivePath, env);
} else { } else {
this.fileSystem = FileSystems.newFileSystem(archivePath, null); this.fileSystem = FileSystems.newFileSystem(archivePath, null);
} }
@ -597,20 +600,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
} }
} }
private FileSystemProvider jarFSProvider;
private FileSystemProvider getJarFSProvider() throws IOException {
if (jarFSProvider != null) {
return jarFSProvider;
}
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
if (provider.getScheme().equals("jar")) {
return (jarFSProvider = provider);
}
}
throw new ProviderNotFoundException("no provider found for .jar files");
}
/** /**
* container is a directory, a zip file, or a non-existent path. * container is a directory, a zip file, or a non-existent path.
*/ */

View file

@ -42,6 +42,7 @@ 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.ProviderNotFoundException; import java.nio.file.ProviderNotFoundException;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -315,26 +316,30 @@ public class Locations {
if (fsInfo.isFile(file)) { if (fsInfo.isFile(file)) {
/* File is an ordinary file. */ /* File is an ordinary file. */
if (!isArchive(file) if ( !file.getFileName().toString().endsWith(".jmod")
&& !file.getFileName().toString().endsWith(".jmod") && !file.endsWith("modules")) {
&& !file.endsWith("modules")) { if (!isArchive(file)) {
/* Not a recognized extension; open it to see if /* Not a recognized extension; open it to see if
it looks like a valid zip file. */ it looks like a valid zip file. */
try { try {
// TODO: use of ZipFile should be updated FileSystems.newFileSystem(file, null).close();
ZipFile z = new ZipFile(file.toFile()); if (warn) {
z.close(); log.warning(Lint.LintCategory.PATH,
if (warn) { "unexpected.archive.file", file);
log.warning(Lint.LintCategory.PATH, }
"unexpected.archive.file", file); } catch (IOException | ProviderNotFoundException e) {
// FIXME: include e.getLocalizedMessage in warning
if (warn) {
log.warning(Lint.LintCategory.PATH,
"invalid.archive.file", file);
}
return;
} }
} catch (IOException e) { } else {
// FIXME: include e.getLocalizedMessage in warning if (fsInfo.getJarFSProvider() == null) {
if (warn) { log.error(Errors.NoZipfsForArchive(file));
log.warning(Lint.LintCategory.PATH, return ;
"invalid.archive.file", file);
} }
return;
} }
} }
} }
@ -1054,6 +1059,9 @@ public class Locations {
} catch (IOException e) { } catch (IOException e) {
log.error(Errors.LocnCantReadFile(p)); log.error(Errors.LocnCantReadFile(p));
return null; return null;
} catch (ProviderNotFoundException e) {
log.error(Errors.NoZipfsForArchive(p));
return null;
} }
//automatic module: //automatic module:
@ -1105,13 +1113,9 @@ public class Locations {
fs.close(); fs.close();
} }
} }
} catch (ProviderNotFoundException e) {
// will be thrown if the file is not a valid zip file
log.error(Errors.LocnCantReadFile(p));
return null;
} catch (ModuleNameReader.BadClassFile e) { } catch (ModuleNameReader.BadClassFile e) {
log.error(Errors.LocnBadModuleInfo(p)); log.error(Errors.LocnBadModuleInfo(p));
} catch (IOException e) { } catch (IOException | ProviderNotFoundException e) {
log.error(Errors.LocnCantReadFile(p)); log.error(Errors.LocnCantReadFile(p));
return null; return null;
} }

View file

@ -32,6 +32,7 @@ import java.nio.file.FileSystems;
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.ProviderNotFoundException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -86,7 +87,7 @@ public class JDKPlatformProvider implements PlatformProvider {
} }
} }
} }
} catch (IOException ex) { } catch (IOException | ProviderNotFoundException ex) {
} }
} }
SUPPORTED_JAVA_PLATFORM_VERSIONS.add(targetNumericVersion(Target.DEFAULT)); SUPPORTED_JAVA_PLATFORM_VERSIONS.add(targetNumericVersion(Target.DEFAULT));

View file

@ -1667,6 +1667,10 @@ compiler.warn.invalid.archive.file=\
compiler.warn.unexpected.archive.file=\ compiler.warn.unexpected.archive.file=\
Unexpected extension for archive file: {0} Unexpected extension for archive file: {0}
# 0: path
compiler.err.no.zipfs.for.archive=\
No file system provider is available to handle this file: {0}
compiler.warn.div.zero=\ compiler.warn.div.zero=\
division by zero division by zero

View file

@ -102,6 +102,7 @@ compiler.warn.proc.type.already.exists # JavacFiler: just menti
compiler.warn.unchecked.assign # DEAD, replaced by compiler.misc.unchecked.assign compiler.warn.unchecked.assign # DEAD, replaced by compiler.misc.unchecked.assign
compiler.warn.unchecked.cast.to.type # DEAD, replaced by compiler.misc.unchecked.cast.to.type compiler.warn.unchecked.cast.to.type # DEAD, replaced by compiler.misc.unchecked.cast.to.type
compiler.warn.unexpected.archive.file # Paths: zip file with unknown extn compiler.warn.unexpected.archive.file # Paths: zip file with unknown extn
compiler.err.no.zipfs.for.archive # would need zip/jar file
compiler.warn.unknown.enum.constant # in bad class file compiler.warn.unknown.enum.constant # in bad class file
compiler.warn.unknown.enum.constant.reason # in bad class file compiler.warn.unknown.enum.constant.reason # in bad class file
compiler.warn.override.equals.but.not.hashcode # when a class overrides equals but not hashCode method from Object compiler.warn.override.equals.but.not.hashcode # when a class overrides equals but not hashCode method from Object

View file

@ -0,0 +1,136 @@
/*
* 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.
*/
/**
* @test
* @bug 8153391
* @summary Verify javac behaves properly in absence of zip/jar FileSystemProvider
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* @run main/othervm -limitmods jdk.compiler LimitedImage
*/
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import toolbox.JavacTask;
import toolbox.JarTask;
import toolbox.Task.Expect;
import toolbox.Task.Mode;
import toolbox.Task.OutputKind;
import toolbox.ToolBox;
public class LimitedImage {
public static void main(String... args) throws IOException {
ToolBox tb = new ToolBox();
//showing help should be OK
new JavacTask(tb, Mode.CMDLINE)
.options("--help")
.run().writeAll();
Path testSource = Paths.get("Test.java");
tb.writeFile(testSource, "class Test {}");
//when zip/jar FS is not needed, compilation should succeed
new JavacTask(tb, Mode.CMDLINE)
.classpath()
.files(testSource)
.outdir(".")
.run()
.writeAll();
Path testJar = Paths.get("test.jar").toAbsolutePath();
new JarTask(tb, testJar).run();
List<String> actualOutput;
List<String> expectedOutput = Arrays.asList(
"- compiler.err.no.zipfs.for.archive: " + testJar.toString()
);
//check proper diagnostics when zip/jar FS not present:
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.classpath(testJar)
.options("-XDrawDiagnostics")
.files(testSource)
.outdir(".")
.run(Expect.FAIL)
.writeAll()
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
throw new AssertionError("Unexpected output: " + actualOutput);
}
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.sourcepath(testJar)
.options("-XDrawDiagnostics")
.files(testSource)
.outdir(".")
.run(Expect.FAIL)
.writeAll()
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
throw new AssertionError("Unexpected output: " + actualOutput);
}
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.options("-XDrawDiagnostics",
"--module-path", testJar.toString())
.files(testSource)
.outdir(".")
.run(Expect.FAIL)
.writeAll()
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
throw new AssertionError("Unexpected output: " + actualOutput);
}
expectedOutput = Arrays.asList(
"- compiler.err.no.zipfs.for.archive: " + testJar.toString(),
"1 error"
);
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.classpath()
.options("-XDrawDiagnostics",
"--module-path", testJar.getParent().toString())
.files(testSource)
.outdir(".")
.run(Expect.FAIL)
.writeAll()
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
throw new AssertionError("Unexpected output: " + actualOutput);
}
}
}

View file

@ -128,7 +128,8 @@ public class InheritRuntimeEnvironmentTest extends ModuleTestBase {
new TestCase(base) new TestCase(base)
.testOpts("--module-path", modules.toString(), "--limit-modules", "jdk.compiler") .testOpts("--module-path", modules.toString(), "--limit-modules", "jdk.compiler")
.otherOpts("-XDrawDiagnostics", .otherOpts("-XDrawDiagnostics",
"--module-source-path", src.toString()) "--module-source-path", src.toString(),
"-classpath", "")
.files(findJavaFiles(src)) .files(findJavaFiles(src))
.expect(Task.Expect.FAIL, "compiler.err.module.not.found") .expect(Task.Expect.FAIL, "compiler.err.module.not.found")
.run(); .run();