JavaMemoryModel: Unexpected weakness/divergence in old JVM spec of final fields

From: Bill Pugh (pugh@cs.umd.edu)
Date: Sat Dec 27 2003 - 08:55:06 EST


Steve Dever from Sun pointed out that the old JVM spec for final
fields has a far weaker definition than the JLS spec.

The only restriction on final fields I could find in the JVM spec is
that write-access to final fields is private. From the definition of
putfield:

>Otherwise, if the field is final, it must be declared in the current
>class. Otherwise, an IllegalAccessError is thrown

The same thing applies to static fields.

The spec also says:
> * The descriptions of the instructions putfield and putstatic now
>include a specification of their behavior when a field is final.
>This documents the behavior of existing implementation.

We've been saying all along that JSR-133 overrides both the old JLS
and the old JVM spec. The JSR-133 commmunity review document
described the new semantics of final fields in both the JLS and JVM
spec, and we didn't get any complaints about it. So it seems we are
clear to continue.

However, it is worth doing an extra level of investigation on this. I
checked, and the behavior described in the JVM spec seems to be the
current behavior of the JVM (1.5.0 build 30).

No class files generated by javac should cause problems, so our
primary concern is classfiles created by other language tools, or by
bytecode writing tools.

I think we have two options:
Option 1:
We continue as planned, bring the restrictions on final fields in
bytecode in sync with those in the JLS (e.g., every final field must
be written to exactly once in a constructor, or in the static
initializer for final static fields).

Option 2:
If the accesses to a final field do not respect those provided for by
the JLS, then the field is only write protected, not final in the
sense of JSR-133. We already need write-protected fields to handle
System.in, System.out and System.err. This would just provide a
general way of doing so, although not through Java source code. Note
that this would allow us to implement System.in etc without using JNI
or Unsafe. We would just need to generate a classfile for
java.lang.System in which putstatic instructions were used to change
System.in, System.out and System.err.

The problem with option 1 is that there is a possibility that
somebody might be generating code that depends on the existing
(broken, in my opinion) JVM spec for final fields.

The problem with option 2 is that it would create a confusing
programming model if some final fields were not really final. Having
System.out etc being write protected rather than final is confusing
enough. Never being sure what semantics any particular final field
has is worse.

Thoughts?

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



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