JDK-4676532 : LTP: Unable to get XMLDecoder to use a specific class loader
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_8,windows_xp
  • CPU: x86,sparc
  • Submitted: 2002-04-29
  • Updated: 2017-05-16
  • Resolved: 2003-09-26
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Duplicate :  
Relates :  
Description
It seems to be impossible to get the XMLDecoder class to use a class loader
other than the default systemClassLoader when decoding an XML stream. I've
tested 2 methods to achieve this, both fail....

This is a major issue because it is not possible for example to load
packages into a system using the URLClassLoader and then use XMLDecoder to
instantiate objects contained in those packages.

The attached example demonstrates both attempts I've made to get XMLDecoder
to use a specific ClassLoader.

The code base attached includes a jar test.jar file which contains a simple
test.message class.

Running encode.sh will write a test.xml file representing an instance of
test.message

Running java decode will fail to load Decode the xml, putting test.jar
in the classpath will run java -cp test.jar:. decode

The sample code makes two attempts to use the Decoder.  Both tests
create a URLClassLoader which references test.jar

In the first test an owner object is created which is actually the
class test.message which has been loaded by the URLClassLoader. I then
use this owner object as the owner of XMLDecoder.

In the second test I instantiate XMLDecoder using reflection. The XMLDecoder
class is loaded by URLClassLoader (which has the test.jar reference), but
it still fails to decode.


All tests were run with JDK 1.4.0-b92 on SPARC Solaris 9b58

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b22
2004-06-14

SUGGESTED FIX If this requires an API change then this can only be fixed for tiger. We can come up with an interim solution for Mantis: Statement.classForName should use the Introspector.instantiate() method. The instantiate() method uses the classloader for a class (TBD), the system classloader and then the classloader from the current thread. This could be a good interim solution until a class loader can be explicitly specified through api. ###@###.### 2002-08-08 XMLEncoder should take a classLoader as it's argument. Or perhaps we should add new API: public void setClassLoader(ClassLoader cl) public ClassLoader getClassLoader(); com.sun.beans.ObjectHandler.classForName should examine the decider if it exists. public static Class classForName(String name) throws ClassNotFoundException { // l.loadClass("int") fails. Class primitiveType = typeNameToPrimitiveClass(name); if (primitiveType != null) { return primitiveType; } ClassLoader l = Thread.currentThread().getContextClassLoader(); if (is != null && is.getClassLoader() != null) l = is.getClassLoader(); } return l.loadClass(name); } ###@###.### 2003-09-05
2003-09-05

EVALUATION It appears that the class loading from the name of the class is done through the static method Statement.classForName() method. This method is called from Statement.invoke() and is wrapped and called from XMLDecoder.classForName() - which is called from many places within XMLDecoder. Statement.classForName() only uses the ContextClassLoader from the currentThread and there is no way that you can specify it to use a specific classloader. One possible solution is for the Statment to try loading the class from the classloader of the target object. The strategy would have to be similar to the one implemented in trying to load the explicit BeanInfo class within the Introspector. ###@###.### 2002-05-02 The class lookup within the Introspector should be the model of looking for classes. A good solution to this would be to refactor the static method Introspector instantiate method to use a static "search for class" method. The Statement classForName can use this package private class lookup mehtod. Should be fixed for tiger. Perhaps in mantis if this becomes a larger issue. ###@###.### 2002-05-17
2002-05-17

WORK AROUND The best way that I would recommend doing this is to patch Statement.classForName to try the target class loader first and then use the currentThread context class loader: ClassLoader cl = target.getClassLoader(); if (cl != null) { try { return cl.loadClass(className); } catch (Exception ex) { // fall through } } Prepend this patched java.bean.Statement in front of your bootstrap classpath with -Xbootclasspath:/p. ======================= Another more viable work around is to set the class loader that you want to instantiate within the current thread context: Before instantiating the XMLDecoder, set the classloader that you want to use by: Thread.currentThread().setContextClassLoader(classloader); ###@###.### 2002-05-02
2002-05-02