JEP Draft: Integrity and Strong Encapsulation
openjdk.org
openjdk.org
> Legacy bugs have been fixed so it is exceptionally rare to need to break encapsulation to work around them.
I do think their line of thinking is quite optimistic. Take this famous bug: https://bugs.openjdk.org/browse/JDK-8207840 which was set to Resolved, Won't Fix and instead the recommend a newer API. Here's the thing, a lot of third party code still uses the older API. A major use case is attempting to call the SalesForce API using HTTPUrlConnection or a library that wraps this class... Good luck. Despite SalesForce being extraordinarily common, you simply can't call it using the JDK's standard classes as the SF API required HTTP PATCH.
The only workaround we can find, save building/patching an entire JDK, is at Runtime, to do some dirty things to the JDK with the Reflection and/or Unsafe APIs. We'd love to migrate every app to the latest JDK where HTTP PATCH might be supported, but RuntimePatching allows us to not have to cross that bridge.
As a matter of fact, we have a JVM Agent that intercepts class loads and can patch 3rd Party Libraries on the fly. This allows us to immediately deploy fixes to prod when things like Spring4Shell appear.
I suppose the next layer down the chain is to start patching code with ASM. Ugh.
No, the CLI `--add-opens` CLI option will stay. In other words, applications will need to consciously enable the encapsulation-breaking stuff. Is that bad? Modern software moved to public APIs quite a bit ago. That said, if old applications want to use new JDKs, they will require quite some developement, yes.
That said the writing has been on the wall since Java 9's project Jigsaw. If you have a product that depends on it, I'm surprised you were caught unaware. With more control over what is exported, the amount of compiler optimisations possible greatly increases.
> To balance the need for integrity with both the circumstantial, convenience uses of JDK internals and the essential uses, Java gives the user – the application's owner (typically its author, maintainer, or deployer) – the final say on which strong encapsulation boundaries are in place and which should be ignored. This freedom is offered under the guiding principle that the ability of one component to encroach on the boundaries of another must be explicitly granted by the application. Libraries cannot choose to obtain encapsulation-busting "superpowers" without the knowledge and consent of the application's owner.
The point made in the article is that it's often third-party libraries that do this, breaking invariants in your code. And, with older JVMs, it won't be immediately obvious to you as a user of that library that this is happening.
which may be forever
which might be an acceptable tradeoff if you're shovelling JSON to a websocket
not so good if you're a smart order router trying to hit a level that will be gone in under a microsecond
I suppose it's to avoid sneaky libraries that dynamically starts an agent to crack open the code of the JDK.
He mentioned the Even class, but there didn't seem to be anything that looked to fix the lack of validation when reading from JSON?
If it's out of scope, why bring it up without mentioning further work (or am I missing something)?
The fix is to go through the front door, not the back door.
Whatever deserialisation library/technique you use, it should have to use constructors just like everyone else, because that's where you can put your logic to make sure all your invariants hold.
It is possible to provide your own (de)serialization logic, and so you could, in principle, enforce your invariant there. Unfortunately, to provide custom logic you implement:
private void writeObject(ObjectOutputStream)
private void readObject(ObjectInputStream)
Notably, the deserialization method is not a constructor, which causes problems if you have final fields.You can use the defaultReadObject method to invoke the JVM black magic, then perform your own invariant checks, but you need to know to do this. When the alternative of adding 'implements serializable' you will likely have developers forget that they need to add the checks.
On the glass half full side, at least classes need to opt in to serializeability. There is another universe, where classes are serializable by default.
Having said all of this, Java's serializable is a massive security hole that should never be given untrusted input.