RE: JavaMemoryModel: Legality of native code changing final field s

From: David Holmes (dholmes@dstc.edu.au)
Date: Mon Jun 11 2001 - 22:19:45 EDT


Hi Bill,

> I feel pretty strongly about this. When somebody writes an article
> for JavaWorld advocating the use of JNI to change final fields in
> custom deserialization, I think we need one of three things to be
> true:
>
> * JNI throws an exception if an attempt is made to change a
> final field.
>
> * I can go to the specification and point to a place where is
> says: "If you do this, the semantics of your program are completely
> undefined, and your VM can core dump or produce corrupt and non-typesafe
results."
>
> * The spec defines the semantics of using JNI to change final fields.
>
> (This excludes the write protected fields such as System.in, for
> which some special case will be provided).

This is, unfortunately, a very murky issue. Serialization is broken because
it doesn't allow for the setting of final fields in readObject - hence the
work-around (now that reflection won't let you do it) of using JNI.
De-Serialization acts as a defacto constructor but it doesn't have the
privileges that a constructor has, of being able to set a final field. The
whole interaction of final fields and serialization is a mess. If you ever
find the need to mark a field as "transient final" then watchout. The simple
solution is to stop using final fields - but that's not a very good
solution.

The whole System.* business is a complete debacle but one we are stuck with
forever. It is abhorrent that it must be special cased.

I'm unclear which spec you wish to fix: the JNI spec or the JMM? Certainly
the JNI spec should clarify exactly what the semantics are of changing final
fields but I can't see any attempt at getting JNI to disallow setting of
final fields, being successful, unless the problems that using JNI works
around are solved (even then it is simply too late to make such a change as
no one could possibly guess the impact it would have).

As far as the JMM is concerned I think the visibility guarantees that the
JMM provides for the construction process also need to be made for
psuedo-construction processes like deserialization (and cloning?) (maybe
there is some scope for differences between the two, but certainly I think
de-serialization must be explicitly addressed by the JMM.)

Within the context of those visibility guarantees, the potential for native
code to modify final fields must be accounted for. Informally I would say
that unless the compiler can determine otherwise, a call to a native method
must force a reload of subsequently referenced final fields - but only
within those construction situations.
 
> And if we don't declare using JNI to change final fields to be
> broken, then you can count on somebody with poor taste using it and
> then demanding that JVM's support it. And if they are an important
> application/company, Sun will.

I would be much happier if JNI disallowed the changing of final fields, but
unless the de-serialization issue if fixed (and the System.* - though that
will probably remain special cased in the VM regardless) the JNI can't be
changed. Given that, the JMM need only deal with this issue in the context
of the visibility guarantees it makes for construction.

David Holmes
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:31 EDT