private final static optimization

401 views
Skip to first unread message

Peter Veentjer

unread,
Dec 18, 2016, 3:50:48 AM12/18/16
to mechanical-sympathy
The following question is one out of curiosity of compiler optimization of private final static fields.

I created a very contrived example. The idea is to have some kind of switch that can be enabled/disabled when the JVM starts up.

public class Foo{

   private final static boolean ENABLED = Boolean.getBoolean("bla.enabled");

   private int x;

   public void foo(int x){
    if(ENABLED){
        if(x <0) throw new RuntimeException();
    }
    this.x = x;
   }   
}

The question is if the JIT is allowed to remove the ENABLED check if ENABLED is false. My worry is that due to reflection, one could set the ENABLED to true and therefor the JIT isn't allowed to remove the ENABLED check.

Martin Thompson

unread,
Dec 18, 2016, 5:09:50 AM12/18/16
to mechanical-sympathy

Peter Veentjer

unread,
Dec 18, 2016, 5:12:25 AM12/18/16
to mechanical-sympathy
Hi Martin,

so the JIT is able to remove the if(ENABLED) branch if ENABLED = false?

How does it deal with reflection? The JIT is triggered to deoptimize the code when the ENABLED changes?

Norman Maurer

unread,
Dec 18, 2016, 5:13:08 AM12/18/16
to mechanica...@googlegroups.com
+1

We also do make use of this in Netty (not for disabling bound checks tho).

--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-symp...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Martin Thompson

unread,
Dec 18, 2016, 5:16:32 AM12/18/16
to mechanical-sympathy
Try writing a simple test to see what happens. You can look at the JIT output to see if a deopt occurs. JITWatch can be useful to understanding such things.

Vitaly Davidovich

unread,
Dec 18, 2016, 1:00:19 PM12/18/16
to mechanica...@googlegroups.com
It doesn't care about reflection - modifying final fields via reflection is undefined by the JLS.  Unfortunately, the same optimization isn't done for instance finals because some well known frameworks use that facility.  Oracle is working on ways to mitigate that in a backcompat manner (deopt when it detects such modifications).

But static finals work out of the box already without deopt (the modification isn't visible if done after code is JIT compiled).
--


You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.


To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-symp...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.


--
Sent from my phone

Remi Forax

unread,
Dec 18, 2016, 3:29:29 PM12/18/16
to mechanica...@googlegroups.com
Hi Vitaly,


De: "Vitaly Davidovich" <vit...@gmail.com>
À: mechanica...@googlegroups.com
Envoyé: Dimanche 18 Décembre 2016 19:00:04
Objet: Re: private final static optimization
It doesn't care about reflection - modifying final fields via reflection is undefined by the JLS.  Unfortunately, the same optimization isn't done for instance finals because some well known frameworks use that facility. 

THose frameworks are not wrong, the JLS allows to change final fields when doing deserialization (see JLS 17.5.3) and it's hard for the JIT to know if the reflection is used during a deserialization or not.

Oracle is working on ways to mitigate that in a backcompat manner (deopt when it detects such modifications).

I think, it's easier in the modular world of 9, you know statically if a module uses sun.misc.Unsafe (it has to requires jdk.unsupported transitively) and if a package is open to modification by reflection (the package is declared as open or the module itself is declared as open). A JIT can use this heuristic instead of trying to trap and deopt if a final field change which requires a lot of metadata.


But static finals work out of the box already without deopt (the modification isn't visible if done after code is JIT compiled).
cheers,
Rémi

Vitaly Davidovich

unread,
Dec 18, 2016, 3:51:21 PM12/18/16
to mechanica...@googlegroups.com
Remi,

You're right that serialization is called out, but I always understood that as Java serialization, and not some other type of serialization.  You're right that in practice it's hard to know for the JIT and the practical implication is everyone is allowed to do it, but again, on paper I thought it refers only to builtin serialization.  This is a good example of a feature that's rarely (relatively) used but is an optimization fence for all code.

As for deopt tracking, I believe the current plan is to track this at the class level, not a field - I think this makes it more palatable and doesn't require using modules.  But we'll see how this pans out.

Richard Warburton

unread,
Dec 19, 2016, 3:58:07 AM12/19/16
to mechanica...@googlegroups.com
Hi,

You're right that serialization is called out, but I always understood that as Java serialization, and not some other type of serialization.  You're right that in practice it's hard to know for the JIT and the practical implication is everyone is allowed to do it, but again, on paper I thought it refers only to builtin serialization.  This is a good example of a feature that's rarely (relatively) used but is an optimization fence for all code.

As for deopt tracking, I believe the current plan is to track this at the class level, not a field - I think this makes it more palatable and doesn't require using modules.  But we'll see how this pans out.

I'll be intrigued to see what happens on this front, specifically whether the de-optimisation path traps Unsafe usage. BigInteger is a good example of a JDK class that doesn't use reflection to set a final field, but uses Unsafe, albeit only in serialization.

regards,

  Richard Warburton

Brett Kail

unread,
Dec 19, 2016, 10:59:40 AM12/19/16
to mechanical-sympathy

The thread continued in the next month, but I think the work stalled.  Unsafe was discussed as a major issue, and perhaps it is the reason the work was not finished (waiting until there are suitable replacements so the problematic Unsafe methods can be removed entirely).

Gil Tene

unread,
Dec 19, 2016, 12:09:58 PM12/19/16
to mechanica...@googlegroups.com
As noted before, static finals can be treated as true constants by the JIT (after class initialization). And all JITs seem to do a good job with that. Code guarded by a static final boolean is effectively free (when the boolean is off), except for it's potential impact on inlining decisions in some JITs (which are sometimes driven by byte code counts on the target methods).

The Zing JVM now does what we call "Truly Final" optimization in our latest releases with the Falcon JIT compiler. These optimizations apply to any instance field declared final (private or not doesn't matter), and they allow the JIT to do some important optimizations that were not previously possible. E.g. hoist final field lookups out of loops, and along with them eliminate dependent operations from the loops, like range checks on final arrays. See cool discussion of this "problem" here. Instance fields that have their finality overridden (e.g. via reflection or via Unsafe) will have this optimization dynamically disabled before the override occurs.

Chris Vest

unread,
Dec 19, 2016, 2:45:15 PM12/19/16
to mechanica...@googlegroups.com
On HotSpot you can also get some optimisation benefit out of final instance fields with the flags
-XX:+UnlockExperimentalVMOptions -XX:+TrustFinalNonStaticFields

But as far as I know, HotSpot does not do any deopt when relying on these optimisations are shown to break semantics. Hence its an experimental feature. So you can only use this if you know that, across all of your code and its dependencies, you will never write to a final instance field.

On 19 Dec 2016, at 18.09, Gil Tene <g...@azul.com> wrote:

As noted before, static finals can be treated as true constants by the JIT (after class initialization). And all JITs seem to do a good job with that. Code guarded by a static final boolean is effectively free (when the boolean is off), except for it's potential impact on inlining decisions in some JITs (which are sometimes driven by byte code counts on the target methods).

The Zing JVM now does what we call "Truly Final" optimization in our latest releases with the Falcon JIT compiler. These optimizations apply to any instance field declared final (private or not doesn't matter), and they allow the JIT to do some important optimizations that were not previously possible (e.g. hoist final field lookups out of loops, and along with them eliminate dependent operations from the loops, like range checks on final arrays. See cool discussion of this "problem" here. Instance fields that have their finality overridden (e.g. via reflection or via Unsafe) will have this optimization dynamically disabled before the override occurs.

On Monday, December 19, 2016 at 12:58:07 AM UTC-8, Richard Warburton wrote:
Hi,

You're right that serialization is called out, but I always understood that as Java serialization, and not some other type of serialization.  You're right that in practice it's hard to know for the JIT and the practical implication is everyone is allowed to do it, but again, on paper I thought it refers only to builtin serialization.  This is a good example of a feature that's rarely (relatively) used but is an optimization fence for all code.

As for deopt tracking, I believe the current plan is to track this at the class level, not a field - I think this makes it more palatable and doesn't require using modules.  But we'll see how this pans out.

I'll be intrigued to see what happens on this front, specifically whether the de-optimisation path traps Unsafe usage. BigInteger is a good example of a JDK class that doesn't use reflection to set a final field, but uses Unsafe, albeit only in serialization.

regards,

  Richard Warburton

Vitaly Davidovich

unread,
Dec 19, 2016, 2:53:48 PM12/19/16
to mechanical-sympathy
This only optimizes final field reads when the enclosing object is a static final itself :).  E.g. it'll help uses of Enum::ordinal() and the like, but not much beyond that.

To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages