JDK-8196667 : Multi-release jar handling regressed support for non-default filesystems in JavacFileManager
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 9
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2018-02-02
  • Updated: 2024-10-10
Related Reports
Blocks :  
Relates :  
Description
The following example demonstrates that the multi-release jar handling in JavacFileManager does not support paths to jars in non-default filesystems (in this case JimFS).

Disabling the multi-release jar handling by commenting out the line containing `--multi-release` allows the example to succeed.

=== Test.java
import com.google.common.jimfs.Jimfs;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

class Test {

  public static void main(String[] args) throws Exception {
    FileSystem fs = Jimfs.newFileSystem();
    Path foo = fs.getPath("/foo");
    Files.createDirectory(foo);
    Path hello = foo.resolve("hello.jar");
    try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(hello))) {
      jos.putNextEntry(new JarEntry("Test.class"));
      jos.write(Test.class.getClassLoader().getResourceAsStream("Test.class").readAllBytes());
    }

    JavaCompiler javacTask = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager fileManager = javacTask.getStandardFileManager(null, null, null);

    fileManager.handleOption("--multi-release", Arrays.asList("8").iterator());
    fileManager.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, Arrays.asList(hello));
    fileManager.list(
        StandardLocation.PLATFORM_CLASS_PATH, "", EnumSet.allOf(JavaFileObject.Kind.class), true);
  }
}
===

$ javac -cp jimfs-1.1.jar:guava-23.0.jar Test.java
$ java -cp .:jimfs-1.1.jar:guava-23.0.jar Test
Exception in thread "main" java.lang.UnsupportedOperationException
	at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.newFileSystem(ZipFileSystemProvider.java:128)
	at jdk.compiler/com.sun.tools.javac.file.JavacFileManager$ArchiveContainer.<init>(JavacFileManager.java:517)
	at jdk.compiler/com.sun.tools.javac.file.JavacFileManager.getContainer(JavacFileManager.java:319)
	at jdk.compiler/com.sun.tools.javac.file.JavacFileManager.list(JavacFileManager.java:715)
	at Test.main(Test.java:32)
Comments
Thanks for the link to JDK-8034802.
09-07-2018

> Does it work to load non-MR jars from non-default file systems? Yes, `FileSystems.newFileSystem(path, null)` seems to work for paths to jars on non-default filesystems, but `getJarFSProvider().newFileSystem(hello, null)` does not. The constructor of ArchiveContainer uses the second approach only for MR jars. I agree that the best solution is to fix zipfs.
09-07-2018

This looks like more an issue with the standard jar FileSystemProvider, and less like a problem with javac itself. javac is (intentionally) relying on the underlying file system provider to handle multi-release jars. This is not so much a regression as much as a limitation in the implementation of a new feature.
09-07-2018

Does it work to load non-MR jars from non-default file systems?
09-07-2018