Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8295392

jars in directories which end with '!' fail to load resource bundles

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Tested on OS X 12.6 and windows 10 Pro 21H2 with the same outcome.
      Java 11.0.16.1

      A DESCRIPTION OF THE PROBLEM :
      When running a jar on the classpath which is within a directory which contains the '!' (ascii table 33) character as the LAST character in the name of the directory (i.e. my_directory!) Resource bundles fail to load. This looks to be due to an issue in java.net.JarUrlConnection where the first index of '!' is used (INCORRECT). This differs from sun.net.www.protocol.jar.Handler which uses the last index of '!' (CORRECT)
      This results in ResourceBundle.getBundle("some_bundle") failing to be resolved correctly as the directory is resolved instead of the jar itself.
      Furthermore, Im not sure of the ramifications of jar loading internally, but if you place a jar file next to that parent directory with the same name it looks like it looks for the requested entries in that jar instead of the intended one, even if that jar is not on the classpath.



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Setup for basic failure:
      1. have a jar in some directory which contains a directory in its path whose name ends with '!'
      2. that jar should attempt to load a ResourceBundle which is contained within that jar via classpath

      ``` bash
      $ tree .
      .
      ├── directory!
      │   └── jar-test.jar
      └── test.sh

      1 directory, 2 files
      $ cat test.sh

      #!/bin/sh
      java -classpath 'directory!/jar-test.jar' io.test.Main
      ```

      Setup for escape failure:
      1. have a jar in some directory which contains a directory in its path whose name ends with '!'
      2. that jar should attempt to load a ResourceBundle which is contained within that jar via classpath, but instead will look in the jar which matches the name of the directory ending with '!'

      ``` bash
      tree .

      .
      ├── directory.jar
      ├── directory.jar!
      │   └── jar-test.jar
      └── test.sh

      1 directory, 3 files
      $ cat test.sh

      #!/bin/sh
      java -classpath 'directory.jar!/jar-test.jar' io.test.Main
      ```

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      A jar file, regardless of the name of any of its parent directories should resolve Resource Bundles without issue.
      A jar file matching any of the parent directory names should not be used to look for entries, especially when not even declared on the classpath.
      ACTUAL -
      $ java -classpath 'directory!/jar-test.jar' io.test.Main

      attempting to load 'some_bundle' resource bundle..
      Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name some_bundle, locale en_US
      at java.base/java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:2055)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1689)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1593)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1556)
      at java.base/java.util.ResourceBundle.getBundle(ResourceBundle.java:857)
      at io.test.Main.main(Main.java:8)
      Caused by: java.nio.file.NoSuchFileException: /Users/XXX/myRepos/jar-issue/demo/directory
      at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
      at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
      at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
      at java.base/sun.nio.fs.UnixFileAttributeViews$Basic.readAttributes(UnixFileAttributeViews.java:55)
      at java.base/sun.nio.fs.UnixFileSystemProvider.readAttributes(UnixFileSystemProvider.java:149)
      at java.base/java.nio.file.Files.readAttributes(Files.java:1764)
      at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1273)
      at java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:845)
      at java.base/java.util.zip.ZipFile$CleanableResource$FinalizableResource.<init>(ZipFile.java:871)
      at java.base/java.util.zip.ZipFile$CleanableResource.get(ZipFile.java:860)
      at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:262)
      at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:191)
      at java.base/java.util.jar.JarFile.<init>(JarFile.java:350)
      at java.base/sun.net.www.protocol.jar.URLJarFile.&lt;init&gt;(URLJarFile.java:103)
      at java.base/sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:72)
      at java.base/sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:84)
      at java.base/sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:125)
      at java.base/sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:155)
      at java.base/java.util.ResourceBundle$Control$1.run(ResourceBundle.java:3227)
      at java.base/java.util.ResourceBundle$Control$1.run(ResourceBundle.java:3216)
      at java.base/java.security.AccessController.doPrivileged(Native Method)
      at java.base/java.util.ResourceBundle$Control.newBundle(ResourceBundle.java:3215)
      at java.base/java.util.ResourceBundle.loadBundle(ResourceBundle.java:1994)
      at java.base/java.util.ResourceBundle.findBundle(ResourceBundle.java:1776)
      at java.base/java.util.ResourceBundle.findBundle(ResourceBundle.java:1728)
      at java.base/java.util.ResourceBundle.findBundle(ResourceBundle.java:1728)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1662)
      ... 4 more

      Escaping directory to look in jar not loaded for entries:
      $ java -classpath 'directory.jar!/jar-test.jar' io.test.Main

      attempting to load 'some_bundle' resource bundle..
      Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name some_bundle, locale en_US
      at java.base/java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:2055)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1689)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1593)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1556)
      at java.base/java.util.ResourceBundle.getBundle(ResourceBundle.java:857)
      at io.test.Main.main(Main.java:8)
      Caused by: java.io.FileNotFoundException: JAR entry jar-test.jar!/some_bundle.properties not found in /Users/XXX/jar-issue/demo/directory.jar
      at java.base/sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:147)
      at java.base/sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:155)
      at java.base/java.util.ResourceBundle$Control$1.run(ResourceBundle.java:3227)
      at java.base/java.util.ResourceBundle$Control$1.run(ResourceBundle.java:3216)
      at java.base/java.security.AccessController.doPrivileged(Native Method)
      at java.base/java.util.ResourceBundle$Control.newBundle(ResourceBundle.java:3215)
      at java.base/java.util.ResourceBundle.loadBundle(ResourceBundle.java:1994)
      at java.base/java.util.ResourceBundle.findBundle(ResourceBundle.java:1776)
      at java.base/java.util.ResourceBundle.findBundle(ResourceBundle.java:1728)
      at java.base/java.util.ResourceBundle.findBundle(ResourceBundle.java:1728)
      at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1662)
      ... 4 more

      ---------- BEGIN SOURCE ----------
      import java.util.ResourceBundle;

      public class Main {
          public static void main(String[] args) {
              System.out.println("attempting to load 'some_bundle' resource bundle..");
              ResourceBundle bundle = ResourceBundle.getBundle("some_bundle");
              System.out.println(bundle.getString("loaded"));
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Run the jar from a directory which doesn't end with '!'. (while this sounds simple, there are conceivably times when this is not so simple)

      FREQUENCY : always


            michaelm Michael McMahon
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: