Thanks Yuval for bringing this to our attention, but I'm not sure the patch should go in. The optimizing compiler folds final fields, for example:
class BooleanHolder {
private final boolean value;
BooleanHolder (boolean val) { this.value = val; }
boolean getValue() {return value;}
}
class Test {
static final BooleanHolder DEBUG = new BooleanHolder(false);
public static void main (String[] args) {
if (DEBUG.getValue()) { System.out.println("Hey we're debugging stuff!"); }
}
}
Ideally in main in the optimizing compiler we'll see that DEBUG can only be one object (assuming the class is initialized) and that value in BooleanHolder has a final value. We take that final value and use it as a constant within the optimizing compiler. This means that the optimizing compiler entirely removes the if(DEBUG...){...} code.
This is not only an important optimization in application code, but we rely quite heavily upon it in the RVM and MMTk to fold away possible costs of having flexible implementations.
What the patch allows is that reflection code would be able to toggle the value of the BooleanHolder which isn't something normal application code would be able to do. This could yield unexpected behavior and given our final field folding is aggressive, we're likely to see errors. It strikes me as cleaner to throw the illegal access exception.
Final fields are a notoriously buggy concept, in particular if this is allowed to escape during object construction then the final field may not have been initialized (see unsafe construction - this is really scary given what our optimizing compiler can do, but it never happens in practice/our regression test set).
The new problem is how to fix this properly? Its certainly the case that Sun's VM lets you do this, but maybe this is because of legacy compatibility and something they couldn't walk away from.
It strikes me that if we were to implement this we'd need to take better control of accessibility and either deny permission to change values that had been folded during optimization or invalidate methods that were compiled assuming final values. The former wouldn't bring us into line with Sun and the latter is likely to have significant runtime cost. Because of this my feeling is this bug should be closed as a "Won't Fix" and that we accept the difference from Sun's JVM. I won't do this immediately so others can post feedback.
Thanks Yuval for bringing this to our attention, but I'm not sure the patch should go in. The optimizing compiler folds final fields, for example:
class BooleanHolder {
private final boolean value;
BooleanHolder (boolean val) { this.value = val; }
boolean getValue() {return value;}
}
class Test {
static final BooleanHolder DEBUG = new BooleanHolder(false);
public static void main (String[] args) {
if (DEBUG.getValue()) { System.out.println("Hey we're debugging stuff!"); }
}
}
Ideally in main in the optimizing compiler we'll see that DEBUG can only be one object (assuming the class is initialized) and that value in BooleanHolder has a final value. We take that final value and use it as a constant within the optimizing compiler. This means that the optimizing compiler entirely removes the if(DEBUG...){...} code.
This is not only an important optimization in application code, but we rely quite heavily upon it in the RVM and MMTk to fold away possible costs of having flexible implementations.
What the patch allows is that reflection code would be able to toggle the value of the BooleanHolder which isn't something normal application code would be able to do. This could yield unexpected behavior and given our final field folding is aggressive, we're likely to see errors. It strikes me as cleaner to throw the illegal access exception.
Final fields are a notoriously buggy concept, in particular if this is allowed to escape during object construction then the final field may not have been initialized (see unsafe construction - this is really scary given what our optimizing compiler can do, but it never happens in practice/our regression test set).
The new problem is how to fix this properly? Its certainly the case that Sun's VM lets you do this, but maybe this is because of legacy compatibility and something they couldn't walk away from.
It strikes me that if we were to implement this we'd need to take better control of accessibility and either deny permission to change values that had been folded during optimization or invalidate methods that were compiled assuming final values. The former wouldn't bring us into line with Sun and the latter is likely to have significant runtime cost. Because of this my feeling is this bug should be closed as a "Won't Fix" and that we accept the difference from Sun's JVM. I won't do this immediately so others can post feedback.