ShenandoahOptimizeFinals is an illegal optimization
Roman Kennke
rkennke at redhat.com
Wed Oct 18 12:51:09 UTC 2017
Am 18.10.2017 um 14:25 schrieb Roland Westrelin:
> This is a follow up to:
>
> http://mail.openjdk.java.net/pipermail/shenandoah-dev/2017-October/003960.html
>
> If we have something like:
>
> public class TestFinal {
> final int field;
> static TestFinal tf;
> TestFinal() {
> tf = this;
> field = 0x42;
> }
>
> public static void main(String[] args) {
> new TestFinal();
> // read tf.field
> }
> }
>
> the object can be evacuated while it is being constructed between the 2
> assignments. In that case tf points to from space with a value of zero
> for field "field". If tf.field is used later own, because field is
> final, with +ShenandoahOptimizeFinals, there will be no read barrier (in
> compiled code), so it will read 0 instead of 42.
>
> I observe something similar in practice with
> sun.security.jca.ProviderList:
>
> private final List<Provider> userList = new AbstractList<Provider>() {
> public int size() {
> return configs.length;
> }
> public Provider get(int index) {
> return getProvider(index);
> }
> };
>
> initializes an instance of an inner class which contains a reference to
> ProviderList in a final field. That happens before the instance itself
> is initialized so fields of ProviderList may be set after the object is
> evacuated but userList may have a reference to the object before it is
> evacuated. The following code in java.security.SecureRandom:
>
> private static String getPrngAlgorithm() {
> for (Provider p : Providers.getProviderList().providers()) {
> for (Service s : p.getServices()) {
> if (s.getType().equals("SecureRandom")) {
> return s.getAlgorithm();
> }
> }
> }
> return null;
> }
>
> goes through method size() above which reads configs in ProviderList
> through the final field and may get a null value for configs eventhough
> it was initialized in the evacuated copy.
>
> I'm working on a patch that disables ShenandoahOptimizeFinals for
> instance fields.
>
> Roland.
Ok. That optimization hasn't gained much anyway iirc.
I wonder: if it's broken for instance fields, is it broken for static
fields too, for the same reasons? Replace the constructor with the
<clinit> in your example above and get the same problem, if the Class
instance is evacuated during clinit ? Or is that not possible?
Roman
More information about the shenandoah-dev
mailing list