← Back to context

Comment by cogman10

4 days ago

This is a great change that will undoubtedly cause a lot of headaches.

There's a number of libraries (particularly around serialization/marshaling) which will end up mutating `final` fields. In fact, this is a trick I've pulled once or twice in my own code for "reasons" (generally needing to modify behavior of a library because it was deficient).

I suspect this will be one of those things that ends up requiring java devs everywhere to bump up the versions of the libraries they use.

That's a separate series of JEPs known as "final means final", also starting to land nowadays.

https://openjdk.org/jeps/500

  • I believe these 2 are effectively linked.

    There's a jdk.internal API which will work as an escape hatch, but that does come with the need for non-compliant libraries to switch over to it. That safety hatch also only allows the setting of final fields once before observation (which is generally fine). So if your code is doing something more esoteric that sets a final field multiple times you will be SOL.

    In any case, if you are using the sun.misc.Unsafe methods for setting final and private fields you'll need to update.

>particularly around serialization/marshaling

The solution being to drop those dogshit reflection based libraries as everyone should have done 10 years ago when codegen became more common.

Looking at you, Gson.

  • I swapped to Avaje Jsonb a while ago. Can’t recommend it and the rest of the Avaje libraries enough, especially Ebean instead of Hibernate.

Strict Field Initialization is opt-in. A flag needs to be set in the classfile in order to enable it. So should not effect any existing code.

  • It won't bite initially, it will bite when you go to update your version of javac in the future and this becomes the default. Or when you update a library that just so happened to be compiled with a newer version of javac.

    This particularly matters when you have something likes this

        class Local {
           private final ThirdPartyObject tpo;
        }
    

    or even something like this

        class Local {
          private final LocalDate ld;
        }