JDK-4496398 : MarshalledObject fails with objects loaded from file urls with spaces
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.rmi
  • Affected Version: 1.3.1
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2001-08-24
  • Updated: 2005-01-25
  • Resolved: 2001-08-25
Related Reports
Duplicate :  
Name: bsC130419			Date: 08/24/2001

Space Here 1168>java -version
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)

If the URLClassLoader for a class that is serialized using a MarshalledObject
is made of a files that contain spaces in their path, unmarshalling the object
fails because the space is seen a seperator between urls by the
sun.rmi.server.LoaderHandler.pathToURLs method. This is may be another
problem related to bugID 4273532?

Here is a trival example that demonstrates the problem:

Space Here 1162>ls
ASerializable.java  ser.jar  tstMO.class  tstMO.java
Space Here 1163>pwd
/tmp/Space Here
Space Here 1164>java tstMO
cwd = file:/tmp/Space Here/./
serializable class = class java.lang.Class
serializable codesource = null
Exception in thread "main" java.net.MalformedURLException: no protocol:
        at java.net.URL.<init>(URL.java:473)
        at java.net.URL.<init>(URL.java:376)
        at java.net.URL.<init>(URL.java:330)
        at sun.rmi.server.LoaderHandler.pathToURLs(LoaderHandler.java:387)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:132)
        at sun.rmi.server.MarshalInputStream.resolveClass
        at java.io.ObjectInputStream.inputClassDescriptor
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:366)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:236)
        at java.rmi.MarshalledObject.get(MarshalledObject.java:138)
        at tstMO.main(tstMO.java:21)
Space Here 1165>cat tstMO.java
import java.io.*;
import java.net.*;
import java.rmi.*;
import java.security.*;

class tstMO
   public static void main(String[] args) throws Exception
      File cwd = new File(".");
      File jarFile = new File(cwd, "ser.jar");
      System.out.println("cwd = "+cwd.toURL());
      URL[] urls = {jarFile.toURL()};
      URLClassLoader cl = new URLClassLoader(urls);
      Object serializable = cl.loadClass("ASerializable");
      Class sc = serializable.getClass();
      System.out.println("serializable class = "+sc);
      CodeSource cs = sc.getProtectionDomain().getCodeSource();
      System.out.println("serializable codesource = "+cs);
      MarshalledObject mo = new MarshalledObject(serializable);
      System.out.println("mo.get() ->"+mo.get());

Space Here 1166>cat ASerializable.java

public class ASerializable implements java.io.Serializable
Space Here 1167>jar -tf ser.jar
Space Here 1168>
(Review ID: 130662) 
###@###.### 10/15/04 17:21 GMT

EVALUATION Regarding the JDC/SDN comments of 2005-01-24 and 2006-10-31: Please read the above evaluation notes. The problem described in this bug report occurs because of bug 4273532, which is about a problem with the java.io.File class, not a problem with the RMI implementation. Even though 4273532 is marked as "Closed, will not be fixed" (for compatibility reasons), it is the cause of the failure in this bug report's test case-- it is the cause of why the RMI implementation is getting passed a poorly-formed URL in the test case. Fortunately, the occurrence of 4273532 in the test case can be easily worked around by avoiding the use of the problematic File.toURL method (see workaround). It is an unfortunate historical artifact that the java.net.URL class allows creation of poorly-formed URLs, so it is important to take care not to create them in general. The following excerpt from the java.net.URL specification discusses this issue: The URL class does not itself encode or decode any URL components according to the escaping mechanism defined in RFC2396. It is the responsibility of the caller to encode any fields, which need to be escaped prior to calling URL, and also to decode any escaped fields, that are returned from URL. Furthermore, because URL has no knowledge of URL escaping, it does not recognise equivalence between the encoded or decoded form of the same URL. For example, the two URLs: http://foo.com/hello world/ and http://foo.com/hello%20world would be considered not equal to each other. Note, the java.net.URI class does perform escaping of its component fields in certain circumstances. The recommended way to manage the encoding and decoding of URLs is to use java.net.URI, and to convert between these two classes using URL.toURI() and URI.toURL(). The RMI implementation itself does not use the File.toURL method, in its "marshalling/unmarshalling" code or elsewhere. There is no meaning to reopening this bug (it is a duplicate of 4273532). If you are experiencing a different problem (not the failure demonstrated by this bug report's test case) that seems to be the fault of the RMI implementation, please file a new bug report.

WORK AROUND Do not use the problematic File.toURL() method. Instead, use file.toURI().toURL() or new URL(file.toURI())

EVALUATION The submitter is correct in citing bug 4273532: the problem here is that the string form of a URL (or more generally, URI) is not allowed to contain any spaces, as spaces can be used as URI delimeters (see RFC 2396, section 2.4.3). Therefore, the problem is that when the file system path containing spaces gets converted to a URL, the spaces need to be escaped in the URL encoding-- this should be done by File.toURL, as discussed in 4273532, which is marked as being fixed in Merlin beta. ###@###.### 2001-08-25 Regarding the JDC comments of 2003-08-21: The root cause of the problem described in this bug report remains 4273532, whether or not 4273532 is fixed. The problem occurs when the file system path containing spaces is (badly) transformed into a file: URL, which happens when the File.toURL() method is invoked, before RMI gets involved. RMI is only dealing with URLs, as obtained from the URLClassLoader. Given that File.toURL has bug 4273532, the best way to fix the test case provided in this bug report (assuming J2SE 1.4) is to replace the line URL[] urls = {jarFile.toURL()}; with URL[] urls = {jarFile.toURI().toURL()}; or URL[] urls = {new URL(jarFile.toURI())}; either of which would solve this problem. (The latter might be preferable in order to work around 4679530, but that's a different issue.) ###@###.### 2003-08-22 Regarding the JDC comment of 2004-09-30: Please see the evaluation comments above. This bug (i.e., what causes the provided test case to fail) is a duplicate of 4273532; it is not meaningful to reopen this bug independently of 4273532. In the test case, the problem occurs when it uses the File.toURL method, which has 4273532. Described above is how to avoid 4273532 by avoiding use of the problematic File.toURL method. The RMI implementation itself never invokes the File.toURL method. ###@###.### 10/15/04 17:43 GMT ###@###.### 2005-1-25 20:37:42 GMT