[xstream-user] Invalid final field : a supposed solution for JDK 5.0

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[xstream-user] Invalid final field : a supposed solution for JDK 5.0

Caluwaerts, Alain
Hello,

I recently faced the same problem other people have with
serializing/deserializing final fields using another JVM then the one
provided by Sun. (for example JRockit)
It has everything to do with not supporting the 'sun.misc.Unsafe' class.

Normally final fields should only be used (in my humble opinion), as
static final fields or as final Maps or Collections.

I've tried to make a small change in following method in
PureJavaReflectionProvider :

 protected void validateFieldAccess(Field field)
   {
      if ((Modifier.isFinal(field.getModifiers())) &&
         (!Map.class.isAssignableFrom(field.getType())) &&
<---
         (!Collection.class.isAssignableFrom(field.getType())))
<---
      {
         throw new ObjectAccessException("Invalid final field "
               + field.getDeclaringClass().getName() + "." +
field.getName());
      }
   }

In other words, 'final Map' and 'final Collection' are allowed. And it
works fine for JRockit 1.5.0_03 and Sun 1.5.0_05. (Forced to use
PureJavaReflectionProvider).

I hope this small change can help a lot of people.

Greetings,
Alain Caluwaerts
Scarlet NV
Brussels, Belgium.



Reply | Threaded
Open this post in threaded view
|

RE: [xstream-user] Invalid final field : a supposed solution for JDK 5.0

Jörg Schaible
Hello Alain,

Caluwaerts, Alain wrote on Tuesday, November 15, 2005 11:08 AM:

> Hello,
>
> I recently faced the same problem other people have with
> serializing/deserializing final fields using another JVM then
> the one provided by Sun. (for example JRockit) It has
> everything to do with not supporting the 'sun.misc.Unsafe' class.
>
> Normally final fields should only be used (in my humble
> opinion), as static final fields or as final Maps or Collections.
>
> I've tried to make a small change in following method in
> PureJavaReflectionProvider :
>
>  protected void validateFieldAccess(Field field)
>    {
>       if ((Modifier.isFinal(field.getModifiers())) &&
>          (!Map.class.isAssignableFrom(field.getType())) && <---
>          (!Collection.class.isAssignableFrom(field.getType()))) <---
>       {
>          throw new ObjectAccessException("Invalid final field "
>                + field.getDeclaringClass().getName() + "." +
>       field.getName()); }
>    }
>
> In other words, 'final Map' and 'final Collection' are
> allowed. And it works fine for JRockit 1.5.0_03 and Sun
> 1.5.0_05. (Forced to use PureJavaReflectionProvider).
>
> I hope this small change can help a lot of people.

This is not a general solution. Field#set() of JDK 1.4 states:

"If the underlying field is final, the method throws an IllegalAccessException."

For JDK 1.5 the documentation has changed though:

"If the underlying field is final, the method throws an IllegalAccessException unless setAccessible(true) has succeeded for this field and this field is non-static. Setting a final field in this way is meaningful only during deserialization or reconstruction of instances of classes with blank final fields, before they are made available for access by other parts of a program. Use in any other context may have unpredictable effects, including cases in which other parts of a program continue to use the original value of this field. "

So it is a new behaviour of JDK 1.5 and we can make exceptions if running under such a JDK. So your solution is just valid for actual JDKs not supporting the Sun14ReflectionProvider, implementations for older JDK versions without Sun14ReflectionSupport (as JRockit) will not work.

- Jörg