News for hackers. Stuff that matters.
Re:One Year After Switching from Java to Go: Our Experiences by akoboldfrying on Wednesday February 19, 2025 @03:18AM (#43099845)
> Test using monkey-patching.

TIL Go has monkey-patching.

But since it has monkey-patching, how is it statically typed? Or does Go monkey-patching amount to creating an instance of a defined-on-the-fly subclass?

The latter would be interesting, because Java lets you do this too -- conveniently "new up" an instance of a subclass that you define inline of a given class or interface (this used to be the easiest way to define callbacks, before lambdas came along), so this testing strategy is available to Java too, but seems not to be preferred.

Separate question: IIUC, monkey-patching is convenient if your test code directly needs to create a TestX instead of a real X, but what if you need the test double "deeper down" -- that is, you need an X that creates a Y that creates a TestZ instead of a real Z?

Re:One Year After Switching from Java to Go: Our Experiences by tpm on Wednesday February 19, 2025 @04:53AM (#43100420)
Java doesn't really enable monkey-patching in the style of Javascript, Perl etc. AFAIK, or am I missing something? That you can create anonymous subclasses during runtime is different to e.g. editing methods of existing objects/classes during runtime.
Re:One Year After Switching from Java to Go: Our Experiences by fweimer on Wednesday February 19, 2025 @05:47AM (#43100729)
JVMTI allows method patching: https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.h... The capabilities are somewhat limited, and an enhancement JEP was withdrawn: https://openjdk.org/jeps/159

On the other other, there is a movement to remove such late binding/rebinding features from the Java platform. However, I think JVMTI is expected to remain supported if the agents are loaded ahead of time. Only on-demand loading of agents will be removed from OpenJDK.

Re:One Year After Switching from Java to Go: Our Experiences by gf000 on Wednesday February 19, 2025 @05:51AM (#43100759)
I wouldn't say that there is a movement to remove such late binding features -- the "movement's" primary goal is simply to properly encapsulate and mark any such part of the code (e.g. make it explicit in the module that that should be supported).

That way AOT compilation becomes possible/efficient and dependencies can't hack into other packages in an unmaintainable way without explicit permission from the user, so that updating the JVM and dependencies will be even more streamlined.

Re:One Year After Switching from Java to Go: Our Experiences by fweimer on Wednesday February 19, 2025 @07:55AM (#43101585)
As far as I know, there is no tooling support to propagate these marks to the launcher program even in cases where they can be statically discovered. (This could be similar how dynamic linker agents (audit modules) are handled by the Solaris linker, via DT_AUDIT and DT_DEPAUDIT markers.) Mainly because OpenJDK does not provide a tool (beyond jar) that creates launchers.

This doesn't concern features that have been traditionally abused (such as reflection on core OpenJDK classes), but also harmless (from an encapsulation perspective) uses of JNI, and access to future features such as FFI/Panama. Justification for restricting those as well is not so much OpenJDK updates, I think, but that it could cause crashes that might be blamed on OpenJDK.

Re:One Year After Switching from Java to Go: Our Experiences by akoboldfrying on Wednesday February 19, 2025 @09:43AM (#43102630)
I agree -- I was just trying to guess what OP might have meant by "monkey-patching" when talking about Go (which is TTBOMK statically typed, which precludes what I'd personally call "monkey-patching" at the language level).

Java does have "agents", which enable arbitrary control of bytecode at class loading time -- bytecode in existing .class files can be transformed, or completely new bytecode generated on-the-fly. But generating bytecode just to replace a class with a test double would be insane.

From another comment I learned there's also a separate "Tool Interface" that can do this bytecode-replacement job, but again, it's a huge amount of tricksiness and bother for something more easily and clearly accomplished in source code with a boring old anonymous subclass. (Though it won't work if the class is sealed, or final, or your code uses reflection to check the class name, or...)