JDK-4730642 : '!' within a directory name is misidentified as the jar separator
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 1.3.1_04,1.4.0_01,1.4.1,1.4.2,5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic,windows_xp
  • CPU: generic,x86
  • Submitted: 2002-08-13
  • Updated: 2013-01-02
  • Resolved: 2013-01-02
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
The methods java.lang.Class.getResourceAsStream and java.lang.ClassLoader.getResourceAsStream returns null if an exclamation mark is part of the working dir.
In other words:
Reading from a jar which is stored in a directory which contains an exclamation mark will throw a NullPointerException.

If you read a text file from a jar usually you use the instruction
Inputstream is = getClass().getResourceAsStream("a_file_in_jar");

Usually the method getResourceAsStream returns an Object of class InputStream if the file exists in the jar. But, if you store the jar file in a directory which directoryname contains an exclamation mark, e. g. "!oops" or "bug!" or "Go!Zilla" the method getResourceAsStream will return null instead of an InputStream object. This will cause a NullPointerException if you want to read from the file.

I've found this bug in 1.3.1_04, 1.4.0_01 and 1.4.1 beta in both Solaris and Windows JRE distributions.

Testcase:
---------
1. Make a directory where an exclamation mark is part of the directoryname
and change into that directory
(use ksh and "back slash, exclamation mark") to avoid shell-interpretation)
% ksh
$ mkdir Go\!Zilla
$ cd Go\!Zilla

2. Create source ReadFromJar.java

$ cat ReadFromJar.java
import java.io.*;

public class ReadFromJar {

  public static void main(String[] args) {
    new ReadFromJar();
  }
 
  public ReadFromJar() {
     readTextFromJar("ReadFromJar.java");  
  }
 
  public void readTextFromJar(String s) {
    String thisLine;
    try {
      InputStream is = getClass().getResourceAsStream(s);
      // returns null if a ! is part of the directory name
      BufferedReader br = new BufferedReader (new InputStreamReader(is)); 
      while ((thisLine = br.readLine()) != null) { 
         System.out.println(thisLine);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

3. Compile ReadFromJar.java
$ java -version
java version "1.4.1-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b14)
Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)

$ javac ReadFromJar.java

4. Create a jar file and include source and class
$ jar cfv ReadFromJar.jar ReadFromJar*

5. Run the jar file, it should output the source code, but it throws an NullPointerException

$ java -classpath ReadFromJar.jar ReadFromJar
java.lang.NullPointerException
        at java.io.Reader.<init>(Reader.java:61)
        at java.io.InputStreamReader.<init>(InputStreamReader.java:55)
        at ReadFromJar.readTextFromJar(ReadFromJar.java:18)
        at ReadFromJar.<init>(ReadFromJar.java:10)
        at ReadFromJar.main(ReadFromJar.java:6)

6. To see that it is usually working, just move the jar to a different directory
$ mv ReadFromJar.jar /tmp
$ cd /tmp
$ java -classpath ReadFromJar.jar ReadFromJar
import java.io.*;

public class ReadFromJar {

  public static void main(String[] args) {
    new ReadFromJar();
  }
 
  public ReadFromJar() {
     readTextFromJar("ReadFromJar.java");  
  }
 
  public void readTextFromJar(String s) {
    String thisLine;
    try {
      InputStream is = getClass().getResourceAsStream(s);
      // returns null if a ! is part of the directory name
      BufferedReader br = new BufferedReader (new InputStreamReader(is)); 
      while ((thisLine = br.readLine()) != null) { 
         System.out.println(thisLine);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}



Comments
WORK AROUND Move the jar file into a directory where the directoryname not contains any excamation marks OR Rename the directory where the jar file is stored, temporarily.
11-06-2004

EVALUATION This bug has been here since at least jdk1.2. ClassLoader.getResourceAsStream is masking the IOException. Class.getResource returns a url of: jar:file:/home/iag/work/bug/lang/cl/4730642/f!oo/rfj.jar!/ReadFromJar.java The '!' in the directory name is interfering with the syntax of a jar url. According to the specification for Jar URLs found in java.net.JarURLConnection, "!/" should be recognized as the separator for a jar entry, not simply a '!' as in the above example. This is a bug. Assuming that "!/" is correctly recognized as the separator, there will still be a problem if the directory name ends with a '!'. The only true solution would be to introduce a quoting mechanism. -- iag@sfbay 2002-08-13
13-08-2002