JDK-4294586 : NoClassDefFoundError if '#' anywhere in path
  • Type: Bug
  • Component: other-libs
  • Sub-Component: other
  • Affected Version: solaris_8u1,1.2.1_04
  • Priority: P2
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_8
  • CPU: generic,sparc
  • Submitted: 1999-11-24
  • Updated: 2015-04-13
  • Resolved: 2000-08-02
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
If there is a pound sign ('#") anywhere in the path of a java program, 
when you try to run the program you get:
     Exception in thread "main" java.lang.NoClassDefFoundError

A pound sign in a path isn't that unusual. Volume Management (vold) 
seems to sometimes use them when creating directory names:

   % ls /cdrom
   cdrom1@           sol_8_sparc_2#1/

In the above example, I am unable to run any of the java installation 
wizards on the mounted cd.

See also bug 4261416.

Comments
EVALUATION Yup... bug in the script... Try moving a Hello.java program into a directory with a # in it and try to run it: mkdir 'foo#bar' mv Hello.java 'foo#bar' cd 'foo#bar' javac Hello.java java Hello Exception in thread "main" java.lang.NoClassDefFoundError: Hello Has something to do with the use of 'dirname' in the script I think. -kto kelly.ohair@Eng 1999-11-28 glenn.skinner@Eng 1999-11-29 Nope. The problem is much more deeply seated. It's a consequence of path names being turned into URLs during the process of class loading. Unfortunately, the URL parsing code [at present...] doesn't know how to escape '#' characters when they're actually part of the path being URL-ified. fred.oliver@East 2000-07-24 While it appears that some code has been affecting File.toURL(), this bug is still reproducible on kestrel/solaris beta refresh. fred.oliver@East 2000-08-02 --------------------------- This problem still exists in Merlin build b25. It has nothing to do with any JVM. There are two distinct cases to test for: cd /tmp/a#b -- in a directory with a '#' java -classpath . Hello (URLClassPath$FileLoader) java -classpath Hello.jar Hello (URLClassPath$JarLoader) This specific problem specificly involves file names (from the classpath) that are converted to URLs in sun.misc.Launcher and converted back to file names in sun.misc.URLClasspath. ++ The new version of File.toURL(), mentioned in related bug reports would handle half the problem, if it were actually used by sun.misc.Launcher. It replaces the '#' character with "%23". Launcher does not use it. ++ If File.toURL() is NOT used, then URLClassPath needs its calls to URL.getFile() to be changed to URL.getPath(), which does not stop at the '#' character. (But it does stop at the '?' character, so yet another problem.) The next failure point is that URLClassPath has two lines of the form url = new URL(getBaseURL(), name); which fail because of the '#' for both class files and jar files. File case: getBaseURL -> "file:/tmp/a#b/" name -> "Hello.class" result -> file:/tmp/Hello.class ???? Jar case: getBaseURL -> "jar:file:/tmp/a#b/Hello.jar!/" name -> "Hello.class" result -> StringOutOfBoundsException -> MalformedURLException ++ If Launcher were changed to use File.toURL(), then there must be code added to URLClasspath to undo the effects (get the '#' back). This can be added in two places. For the JarLoader, add path = ParseUtil.decode(path); before File file = new File(path); For the FileLoader, replace dir = new File(url.getFile().replace('/', File.separatorChar)); with String path = url.getFile().replace('/', File.separatorChar); path = ParseUtil.decode(path); dir = new File(path); These changes work for the jar file case, but there is an additional bug for the class file case: For the directory ending in "/.", File.toURL() returns a URL ending in "/./". When this URL is parsed later, the "/./" is replaced with "/", so that these two URLs will be mis-compared later (one is supposed to be a substring of the other). To fix this, in ParseUtil.encodePath(), replace if (!path.endsWith("/") && directory) { path = path + "/"; } with if (!path.endsWith("/") && directory) { if (path.endsWith("/.")) path = path.substring(0, path.length()-1); else path = path + "/"; } On the whole - I think it might be better to consider avoiding using URLs for files if this can be arranged. This encoding and decoding of strings just wasteful and contributes to increased startup time.
11-06-2004

WORK AROUND Don't use the '#' character in URL's. No other workaround available at this time.
11-06-2004

PUBLIC COMMENTS Any file/directory path that contains the character '#' and is contained in a URL will cause a NoClassDefFoundError exception to be thrown.
10-06-2004