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.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -118,4 +118,19 @@ public class FSInfo {
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.RelativeFile;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
@ -509,7 +510,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
this.archivePath = archivePath;
if (multiReleaseValue != null && archivePath.toString().endsWith(".jar")) {
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 {
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.
*/

View File

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

View File

@ -32,6 +32,7 @@ import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.ProviderNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
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));

View File

@ -1667,6 +1667,10 @@ compiler.warn.invalid.archive.file=\
compiler.warn.unexpected.archive.file=\
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=\
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.cast.to.type # DEAD, replaced by compiler.misc.unchecked.cast.to.type
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.reason # in bad class file
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)
.testOpts("--module-path", modules.toString(), "--limit-modules", "jdk.compiler")
.otherOpts("-XDrawDiagnostics",
"--module-source-path", src.toString())
"--module-source-path", src.toString(),
"-classpath", "")
.files(findJavaFiles(src))
.expect(Task.Expect.FAIL, "compiler.err.module.not.found")
.run();