United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4730642 '!' within a directory name is misidentified as the jar separator
JDK-4730642 : '!' within a directory name is misidentified as the jar separator

Details
Type:
Bug
Submit Date:
2002-08-13
Status:
Closed
Updated Date:
2013-01-02
Project Name:
JDK
Resolved Date:
2013-01-02
Component:
core-libs
OS:
generic,windows_xp
Sub-Component:
java.net
CPU:
x86,generic
Priority:
P4
Resolution:
Duplicate
Affected Versions:
1.3.1_04,1.4.0_01,1.4.1,1.4.2,5.0
Fixed Versions:

Related Reports
Duplicate:
Relates:
Relates:

Sub Tasks

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
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



                                     
2002-08-13
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.
                                     
2004-06-11



Hardware and Software, Engineered to Work Together