History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: XSTR-185
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Assignee: Unassigned
Reporter: Henri Tremblay
Votes: 1
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
XStream

ClassNotFoundException when deserializing Class array type

Created: 07/Feb/05 01:54 PM   Updated: 27/Feb/05 05:48 PM
Component/s: None
Affects Version/s: None
Fix Version/s: 1.1.1

JDK version and platform: 1.4.2_06 for Windows


 Description  « Hide
The problem occurs when you deserialize a Class describing an array of objects. For instance MyClass[].class.

The test case would be:

// Class.forName(BasicInxDTO[].class.getName());

FileReader in = new FileReader("test.xml");
Object o = xstream.fromXML(in);
in.close();

test.xml content:
<java-class>[Lcom.mycompany.MyClass;</java-class>

You get a ClassNotFoundException. The tricky thing is if you uncomment the Class.forName line above, it will work perfectly. It also works with classes coming from the JDK (java.lang for instance). So it is important that the test uses a class defined for the test.

The problematic code comes from the JavaClassConverter:

protected Object fromString(String str) {
try { return str.equals("void") ? void.class : str.equals("byte") ? byte.class : str.equals("int") ? int.class : str.equals("long") ? long.class : str.equals("float") ? float.class : str.equals("boolean") ? boolean.class : str.equals("double") ? double.class : str.equals("char") ? char.class : str.equals("short") ? short.class : classLoader.loadClass(str);// <- Here } catch (ClassNotFoundException e) { throw new ConversionException("Cannot load java class " + str, e); }
}

It seems that the class loader (at least the Sun class loader) is not able to instantiate an array class. The fact that it works when the class is already loaded is probably that it's found in the class loader class cache.

The proposed fix is:

protected Object fromString(String str) {
try { return str.equals("void") ? void.class : str.equals("byte") ? byte.class : str.equals("int") ? int.class : str.equals("long") ? long.class : str.equals("float") ? float.class : str.equals("boolean") ? boolean.class : str.equals("double") ? double.class : str.equals("char") ? char.class : str.equals("short") ? short.class : Class.forName(str, false, classLoader); // <- The fix } catch (ClassNotFoundException e) { throw new ConversionException("Cannot load java class " + str, e); } }
}

It goes through the normal class loading process and arrays are correctly handled.



 All   Comments   Change History      Sort Order: Ascending order - Click to sort in descending order
Joe Walnes - 08/Feb/05 07:24 AM
Thanks for notifying me of this.

I've scheduled the fix to appear in the next release.

cheers
-Joe


Joe Walnes - 16/Feb/05 04:22 PM
Latest snapshot contains this fix

Roger Thornhill - 27/Feb/05 05:48 PM
Hello -

I am not sure that this is fixed. I downloaded the latest snapshot on Feb 26th and I had problems trying to run the following:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;

import com.thoughtworks.xstream.XStream;

public class Foo
{
private int x = 100;

public void printX() { System.out.println(x); }

public static void toXML() throws Exception
{
XStream xstream = new XStream();
Foo[] foos = new Foo[100];
for (int i=0; i<foos.length; i++) { foos[i] = new Foo(); }
String theXml = xstream.toXML(foos);
PrintWriter pw = new PrintWriter(new FileWriter("tmp.dat"));
pw.println(theXml);
pw.flush();
pw.close();
}

public static void fromXML() throws Exception
{
XStream xstream = new XStream();
BufferedReader reader = new BufferedReader(new FileReader("tmp.dat"));
String theXml = "";
while (reader.ready()) { theXml += reader.readLine(); }
Foo[] f = (Foo[])xstream.fromXML(theXml);
for (int i=0; i<f.length; i++) { f[i].printX(); }
}

public static void main(String[] args) throws Exception
{
if (args.length>0 && args[0].equals("to")) { toXML(); }
else { fromXML(); }
}
}