[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Loader in ObjectStreamClass.readClassDescriptor
From: |
Nicolas Geoffray |
Subject: |
Loader in ObjectStreamClass.readClassDescriptor |
Date: |
Fri, 22 Jul 2005 15:41:53 +0200 |
User-agent: |
Mozilla Thunderbird 1.0.5 (X11/20050719) |
Hello again,
There's something that, I think, misbehaves in readClassDescriptor.
Fields are read before the loading of the actual object's class CL in
the stream, which is necessary. When loading the classes of the fields
(before loading CL), the classloader given is the callersClassLoader
which is set to currentLoader() the most recent user defined classloader
on the execution stack.
When using the method with RMI here is the class context :
class java.io.VMObjectInputStream$1
class java.security.AccessController
class java.io.VMObjectInputStream
class java.io.ObjectInputStream
class java.io.ObjectInputStream
class java.io.ObjectInputStream
class java.io.ObjectInputStream
class gnu.java.rmi.server.RMIObjectInputStream
class gnu.java.rmi.server.UnicastServerRef
class gnu.java.rmi.server.UnicastServer
class gnu.java.rmi.server.UnicastServer
class gnu.java.rmi.server.UnicastConnection
class java.lang.Thread
class java.lang.VMThread
So the callersClassLoader is set to null and the fields of CL are loaded
with the VM ClassLoader (which won't found any classes loaded by the
application class loader or other user defined classloader)
Because RMI redefines the resolveClass(ObjectStreamClass), CL is found,
as it used the "correct" classloader. The problem arrives when CL was
loaded by MyClassLoader, and CL has one field whose class was also
loaded by MyClassLoader.
What I suggest is to use the classloader of CL, once CL is loaded, to
load the fields. What i do in the attached patch is reading the fields
and storing them in a temporary class, loading CL as it was done before
(this is when the RMI's resolveClass is used :
gnu.java.rmi.server.RMIObjectInputStream) and finally loading the fields
with CL's classloader.
Would that be a correct behaviour?
Cheers
Nicolas
*** java/io/ObjectInputStream.java Fri Jul 15 15:57:35 2005
--- java/io/ObjectInputStream.java Fri Jul 22 15:36:01 2005
***************
*** 468,473 ****
--- 468,484 ----
}
}
+
+ private class TemporaryStreamField{
+ String field_name;
+ String class_name;
+
+ TemporaryStreamField(String field, String clazz){
+ field_name = field;
+ class_name = clazz;
+ }
+ }
+
/**
* This method reads a class descriptor from the real input stream
* and use these data to create a new instance of ObjectStreamClass.
***************
*** 497,509 ****
short field_count = this.realInputStream.readShort();
if(dump) dumpElementln(Short.toString(field_count));
ObjectStreamField[] fields = new ObjectStreamField[field_count];
ObjectStreamClass osc = new ObjectStreamClass(name, uid,
flags, fields);
assignNewHandle(osc);
- if (callersClassLoader == null)
- callersClassLoader = currentLoader();
-
for (int i = 0; i < field_count; i++)
{
if(dump) dumpElement(" TYPE CODE=");
--- 508,518 ----
short field_count = this.realInputStream.readShort();
if(dump) dumpElementln(Short.toString(field_count));
ObjectStreamField[] fields = new ObjectStreamField[field_count];
+ TemporaryStreamField[] temp_fields = new
TemporaryStreamField[field_count];
ObjectStreamClass osc = new ObjectStreamClass(name, uid,
flags, fields);
assignNewHandle(osc);
for (int i = 0; i < field_count; i++)
{
if(dump) dumpElement(" TYPE CODE=");
***************
*** 521,529 ****
class_name = (String)readObject();
else
class_name = String.valueOf(type_code);
!
! fields[i] =
! new ObjectStreamField(field_name, class_name, callersClassLoader);
}
/* Now that fields have been read we may resolve the class
--- 530,537 ----
class_name = (String)readObject();
else
class_name = String.valueOf(type_code);
!
! temp_fields[i] = new TemporaryStreamField(field_name, class_name);
}
/* Now that fields have been read we may resolve the class
***************
*** 558,563 ****
--- 566,577 ----
throw cnfe;
}
+ ClassLoader loader = clazz.getClassLoader();
+ for(int i =0; i < field_count; i++)
+ fields[i] = new ObjectStreamField(temp_fields[i].field_name,
+ temp_fields[i].class_name, loader);
+
+
boolean oldmode = setBlockDataMode(true);
osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
classLookupTable.put(clazz, osc);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Loader in ObjectStreamClass.readClassDescriptor,
Nicolas Geoffray <=