8 ms·
https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-final-fields/ https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-f... is a damned shame. User
by quotemstr 2y ago
https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-final-fields/ https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-f... is a damned shame. User code misses out on an important optimization available only to system-provided classes because certain frameworks have abused JNI and reflection to mutate final fields, which by all rights should be immutable.
Platforms, especially compilers and runtimes, need to be absolutely strict in enforcing semantic restrictions so as to preserve optimization opportunities for the future.
- J-Kuhn 2y agoYes, but you would be surprised how many people want to change static final fields for various reasons - be it testing, or other things. When telling those that it doesn't work, and that it can not work without violating the semantics of the JVM, they will wave their hand and say "look, it does work here". And it looks like, yes, if the stars align in that specific constellation, it may work.
- deleted 2y ago[deleted]
- hinkley 2y agoAlso a part of why Singletons are the black sheep of the Patterns family. They’re nasty during bootstrapping and hell during functional testing.
- bobnamob 2y agoI’ll be the first to admit that I’ve written the evil three liner to “un-final”, mutate, re-final a member off in some long forgotten internal library to dodge a gnarly refactor. I do wish that I couldn’t have done so, shrug, business needs
- blibble 2y agothe System.out thing is Java itself https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.4 https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.htm... given this it's not surprising others thought it was acceptable also
- deepsun 2y agoI wonder if it thanks to some people blindly following Effective Java book that made a sin by saying "final all the things". So now we cannot easily mock final classes in tests. And mocking tools have to resort to bytecode manipulation to mock the final classes. E.g. Effective Java is a requirement inside Google, so even public GDrive APIs have final classes. External APIs is exactly the thing you'd want to mock.
- lupire 2y agoIf you are rigorous as to make classes final, you should also be rigorous to never provide a non-interface as an Application Programming Interface. Google uses mocks and fakes implementations of interfaces, and provides dependency injection frameworks for managing these (Guice and Dagger).
- stickfigure 2y agoI once worked with a guy who obsessively made interfaces for every java class. Even domain objects. He was extremely proud of this. It was garbage.
- redditor98654 2y agoWas this in Amazon? If so, it might have been me. Sorry about that. I have learnt my lesson now. I don’t recall doing it for domain objects though.
- adamnew123456 2y agoI would say less overuse of final, more underuse of interfaces. If everything takes/returns/stores values by interfaces (excluding data containers with no behavior) then you don't need to "jailbreak" any class to mock it. Of course you get code bloat defining interfaces for everything you intend to implement once, and you have to enforce these rules, but this is something that could be made easier. Not in Java, but imagine a language where: - Concrete classes can only be used in new, or in some platform provided DI container. - Methods can only accept interface types and return interface types. - Fields are private only, all public/protected is via properties (or getters/setters, it just has to be declarable in an interface) - You have a ".interface" syntax (akin to ".class" but for types) that refers to the public members of a class without tying you to the concrete class itself. You can use this as a shorthand instead of declaring separate interfaces for everything. Eg. ``` final class GDrive { ... } public Download file(GDrive.interface drive) { ... } class MockDrive implements GDrive.interface { ... } ``` The closest I can think of is a hypothetical typed variant of NewSpeak, but maybe something like this exists already?
- rusk 2y agoField modifiers are a semantic constraint not a security constraint. It is right and proper that you should be able to bypass them with the appropriate backflips. The main issue is safety cause you might modify something that isn’t modifiable and cause a SEGV and that is precisely the concern access modifiers are meant to address.
- blibble 2y agothey certainly were a security constraint back in the day before Java gave up on trying to use the type system for security e.g. SecurityManager for applets will not let you setAccessible(true) on private fields of system classes
- rusk 2y agoYes but that’s the security manager doing it not the field modifiers. It’s just reusing the modifiers as security metadata.
- elric 2y agoIIRC illegal access can be locked down and be controlled in a fine grained manner with the add-opens and illegal-access flags on newer JVMs.
- pron 2y agoAs part of our "integrity by default" strategy [1] we're changing that. There will be a JEP about it soon. The idea is that because not much code actually needs to mutate finals (and even if it does, that operation is already limited today to classes in the code's own modules or ones explicitly "open" to it), the application will need to grant a permission to a module that wants to mutate finals, similar to how we've recently done things with native calls and unsafe memory access. [1]: https://openjdk.org/jeps/8305968 https://openjdk.org/jeps/8305968