JarFile constructor throws undocumented exception (only) on Windows OS

Jaikiran Pai jai.forums2013 at gmail.com
Thu Oct 4 09:36:23 UTC 2018


Please consider the following trivial code:

import java.util.jar.*;
import java.io.*;

public class JarFileTest {
    public static void main(final String[] args) throws Exception {
        final String tmpDir = System.getProperty("java.io.tmpdir");
        try {
            final JarFile jarFile = new JarFile(tmpDir + File.separator
+ "*");
        } catch (IOException ioe) {
            System.out.println("Got the expected IOException " + ioe);
        }
    }
}

The constructor of the JarFile is passed a string which intentionally is
an (wildcard) invalid path. The above code (as expected) throws an
IOException on *nix systems across various version of Java (tested
against Java 8, 11). The same code throws an IOException (as expected)
in Java 8 on Windows OS too. However, in Java 11, on Windows OS, this
code throws a different exception (java.nio.file.InvalidPathException)
which isn't IOException or a subclass of it:

Exception in thread "main" java.nio.file.InvalidPathException: Illegal
char <*> at index 38: C:\Users\someone\AppData\Local\Temp\1\*
at
java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
at
java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:229)
at java.base/java.io.File.toPath(File.java:2290)
at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1220)
at
java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:727)
at java.base/java.util.zip.ZipFile$CleanableResource.get(ZipFile.java:845)
at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:245)
at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:175)
at java.base/java.util.jar.JarFile.<init>(JarFile.java:341)
at java.base/java.util.jar.JarFile.<init>(JarFile.java:312)
at java.base/java.util.jar.JarFile.<init>(JarFile.java:251)
at JarFileTest.main(JarFileTest.java:8)


The javadoc of JarFile constructor(s) mentions that:

     * @throws IOException if an I/O error has occurred

Given that the javadoc doesn't mention anything about this other
exception, would this throwing of java.nio.file.InvalidPathException be
considered a bug in the implementation?

If this indeed is considered a bug, it appears to be the code in
java.util.zip.ZipFile$Source.get method which calls File#toPath(), which
as per its javadoc is indeed expected to throw an
java.nio.file.InvalidPathException if a Path cannot be constructed out
of the File. Looking at the implementation of the underlying
java.nio.file.FileSystem on *nix and Windows, they differ when it comes
to whether or not the exception gets thrown (Unix one seems to always
return a result). But keeping the implementation of
java.nio.file.FileSystem aside, I guess the
java.util.zip.ZipFile$Source.get code needs to have a catch block for
the InvalidPathException to wrap that into a IOException? Something like:


# HG changeset patch
# User Jaikiran Pai <jaikiran.pai at gmail.com>
# Date 1538645309 -19800
#      Thu Oct 04 14:58:29 2018 +0530
# Node ID ff1bfd8cc9a3b385716fa5191bb68989d552f87e
# Parent  8705c6d536c5c197d0210acccf145ebc48f90227
Wrap and throw an IOException when a InvalidPathException is thrown

diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java
b/src/java.base/share/classes/java/util/zip/ZipFile.java
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java
@@ -35,6 +35,7 @@
 import java.lang.ref.Cleaner.Cleanable;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.InvalidPathException;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.nio.file.Files;
 import java.util.ArrayDeque;
@@ -1218,8 +1219,13 @@
 
 
         static Source get(File file, boolean toDelete) throws IOException {
-            Key key = new Key(file,
-                              Files.readAttributes(file.toPath(),
BasicFileAttributes.class));
+            final Key key;
+            try {
+                key = new Key(file,
+                        Files.readAttributes(file.toPath(),
BasicFileAttributes.class));
+            } catch (InvalidPathException ipe) {
+                throw new IOException(ipe);
+            }
             Source src;
             synchronized (files) {
                 src = files.get(key);


Any thoughts?


-Jaikiran



More information about the core-libs-dev mailing list