#139 ClassNotFoundException w/ arrays due to Classloader approach

Dozer v.4.3
closed-fixed
None
5
2008-11-04
2008-04-17
insitedata
No

Dozer appears to be loading arrays via a non-recommended approach in the ClassLoader.

The ClassLoader.loadClass() method sometimes has problems loading array objects defined in the mapping file. The problem occurs when the class hasn’t been loaded into the JVM prior to instantiation of the mapper. Per the forum entry below, dozer is using ClassLoader.loadClass(). Evidently, this is not the recommended approach by Sun with arrays (although it worked before due to a JDK bug). The dozer approach will work if the array has already been loaded. I found that it did fail with 1.4.2._15 when it doesn’t. The workaround is to reference the class array before instanitating the mapper (sample is below). With the class loaded, Dozer works ok. I also failed with JDK 1.5.0_11.

Dozer workaround code for arrays:

// the next line is a Dozer workaround to load the array into the JVM
Class.forName(com.sample.test.SimpleObj[].class.getName());
// now instantiate the mapper
MapperIF mapper = new DozerBeanMapper(configFiles);

My mapping file:

<converter type="netx.sf.dozer.util.mapping.converters.StringAppendCustomConverter">
<class-a>[Lcom.sample.test.SimpleObj;</class-a>
<class-b>java.lang.String</class-b>
</converter>

Per http://sourceforge.net/forum/message.php?msg_id=4134768:

<<Since the src object is an array, the mapping xml entry I added for the custom converter to get it to work looks strange. Dozer generically uses ClassLoader.loadClass() when parsing the mapping files. For arrays, java expects the class name in the following format.... >>

Sun discussion of the issue: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6446627

<<[When you want to reflectively load a class by name initiated using a specific class loader, you should not invoke that loader's public loadClass method directly-- instead, you should always use the static three-argument Class.forName method. The ClassLoader.loadClass instance method is more intended for delegation from one class loader to another within a class loading operation (although this is a common confusion and not well described in the documentation). In other words, replace L.loadClass(N) with Class.forName(N,false,L). The Class.forName invocation may eventually end up invoking loadClass on the specified loader, but only after taking care of some other aspects of the VM's standard symbolic class name resolution process-- the significant bit in this case being the support for loading/creation of array classes.]

The fact that the ClassLoader.loadClass usage sometimes worked with array class names in previous versions was considered a bug (unintentional behavior) that got fixed in Mustang-- and it did not previously actually "work" fully reliably anyway, which is part of the reason that this "bug" was fixed. There is some related discussion in the text of CR 4976356, and for some further discussion related to serialization usage, see this JINI-USERS post:

http://archives.java.sun.com/cgi-bin/wa?A2=ind0604&L=jini-users&P=1084
>>

Codehaus entry that led me to initially try the Class.forName() workaround:

http://jira.codehaus.org/browse/XSTR-185

Discussion

  • dmitry (lv)

    dmitry (lv) - 2008-10-18
    • milestone: --> Dozer v.4.3
    • assigned_to: nobody --> sterala
     
  • dmitry (lv)

    dmitry (lv) - 2008-11-04
    • assigned_to: sterala --> buzdin
    • status: open --> closed-fixed
     
  • dmitry (lv)

    dmitry (lv) - 2008-11-04

    Could not reproduce the bug on my machine, but changed our implementation to use Class.forName(). It is less sophisticated and more portable way of doing the same thing. Tests are working fine with this change, so I am not worried.

    Thank you for the report.

     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks