bytebuddy predates it by at least a decade.
This came to be, because Oracle noticed everyone, including themselves, were depending on ASM, so the JEP was born.
It's usually not painful to update (just bump the version) but it's an annoyance.
In fact, Byte buddy has a dep on ASM.
https://github.com/square/javapoet
I've used it to do a mass refactoring of an annotation-based library. Worked pretty great.
For others that value the things that Kotlin brings over Java (even modern Java), and for the ways in which it delivers a simpler experience than Scala - I think it's a pragmatic and sensible decision.
val a: SomeType? = null
// I’m forced to null check here
if (a != null) {
a.someMethodOnIt()
}
// But I don’t have to null check here
a.someExtensionFn()
It’s weird.It makes reading a lot of Kotlin source quite terrible.
Lately they've been shoveling a lot of similar magical "code comes from somewhere" features into a language, slowly giving it a C++ clutter type feel.
Java (the language) is pretty much "C for the JVM." By that, I mean frameworks/libraries intended for maximum potential use in languages running on the JVM (such as Kotlin, Scala, and of course Java) all support Java (the language) interoperability. Many written in alternate languages targeting the JVM, such as Akka[0], typically have some degree of Java (the language) support as well.
While I prefer to program in one of the alternate programming languages targeting the JVM, I understand why many OSS projects are implemented in Java (the language) for the reasons outlined above.
It may allow closer to JVM access, however the entire ecosystem is a colossal mess. The main() implementation in having a class that wraps it is pretty dumb, standard stuff like Lombok hacks the AST (not to mention in general the annotation preprocessors work by printing code strings to file), and the whole dependency injection frameworks are very much separated from actual processing with how much stuff they do in the background.
And then there is the whole Apache foundation with its software being used widely as standard. The same foundation where someone wrote the code that allows log statements to pull arbitrary code from the internet and execute it, and that change made its way past multiple eyes before being merged to production without a single person realizing how crazy it is.
If you want speed, write stuff in C/Rust/Clean C++ (without templates, no C style memory access, e.t.c). If you want to be efficient, write stuff in Python/Node.
> If you want to be efficient
Funny that you assume the best position of the trade off continuum isn't somewhere in the middle for most people. Besides, for developer efficiency, I prefer a language where I don't have to constantly worry if the type system is defeated at runtime.
>I prefer a language where I don't have to constantly worry if the type system is defeated at runtime.
If you are doing this with Python, you are doing something very wrong, even without mypy. As for NodeJS, just use Typescript.
This is an opinion of which many would disagree, for various legitimate reasons, yet appears to be the polyglot approach you prefer. So let's briefly explore it.
> I don't know why people are so aghast about writing small C programs, compiling them, and launching them with Python through an os call.
There are significant limitations to using fork[0]/exec[1] as a general purpose component integration strategy, not the least of which is the inability of fine-grained bidirectional interactions.
A better "Python and C" integration option is to employ SWIG[2] to incorporate C/C++ libraries directly into the Python execution environment.
0 - https://man.freebsd.org/cgi/man.cgi?query=fork&apropos=0&sek...
1 - https://man.freebsd.org/cgi/man.cgi?query=execve&sektion=2&a...
Even more so, you can often time prototype in Python with rapid dev, and then when you want performance, you can translate it to pretty much whatever, including C, using LLMs that do a pretty good job. With coding agents, you can set them up to basically run the code side by side against a bunch of inputs and automatically fix stuff. We pretty much did this at our job to translate an internal API backend to a web server written purely in C, that was fully memory safe without any memory bugs.
I constrain my LLM-generated Java code to only static methods of 20 LOC or less, and limit data types to those that are JSON compatible. Both of these lead to more reliable code and data that Claude Code fully understands and generates.
I am preparing to auto-generate an agent-based application that might reach 1.5 million Java LOC. Hard to imagine accomplishing that with Javascript or Python or C++.
Where did it get it from?
https://github.com/iluwatar/java-design-patterns
https://github.com/spring-projects/spring-framework
https://github.com/apache/kafka
https://github.com/inforkgodara/store-poshttps://github.com/...
I also have a markdown-formatted document `core-programming-guidelines.md` that I include in the Claude Code code-generation prompt.
For example:
## Core Programming Principles
### Defensive Programming & Safety 1. *Use 'final' keyword aggressively* for method parameters, local variables, and class fields 2. *Null Safety*: Include null checks with Validate.notNull() and assertions for external calls 3. *Input Validation*: Validate all method parameters with clear preconditions using org.apache.commons.lang3.Validate
### Performance Optimization 1. *Collection Sizing*: Always provide calculated initial capacity for collections 2. *String Processing*: Use StringBuilder with pre-calculated capacity, avoid regex where possible and avoid `java.util.Scanner` where possible. 3. *Memory Management*: Clear large collections when done, reuse objects where appropriate
### Code Clarity & Documentation 1. *Naming Conventions*: Use descriptive names for variables, methods, and constants - All StringBuilder variables should be suffixed `Builder`. 2. *Documentation*: Comprehensive JavaDoc for all public, protected, and private methods 3. *Inline Comments*: Explain complex logic, algorithms, and business rules
### Modern Java 23 Features 1. *Text Blocks*: Use for multi-line string literals 2. *Pattern Matching*: Use where appropriate for cleaner code 3. *Records*: Use for immutable data carriers 4. *Enhanced Switch*: Use new switch expressions
- There are how many computer architectures? A compile-once-run-anywhere binary looks closer to shipping a fancy interpreter with your code than shipping a compiled project. Runtime bytecode generation is one technique for making that fast.
- More generally, anything you don't know till runtime generates a huge amount of bloat if you handle it at compile-time. Imagine, e.g., a UI for dragging and dropping ML components to create an architecture. For as much compute as you're about to pour into training, even for very simple problems, it's worth something that looks like a compilation pass to appropriately fuse everything together. You could probably get away with literally shipping a compiler, but bytecode generation is a reasonable solution too.
- Some things are literally impossible at compile-time without boxing and other overhead. E.g., once upon a time I made a zero-cost-abstraction library allowing you to specify an ML computational graph using the type system (most useful for problems where you're not just doing giant matmuls all day). It was in a language where mutually recursive generics are lazily generated, so you're able to express arbitrary nth derivatives still in the type system, still with zero overhead. What you can't do though is create a runtime program capable of creating arbitrary derivatives; there must be an upper bound for any finite-sized binary (for sufficiently complex starting functions) -- you could cap it at 2nd derivatives or 10th or whatever, but there would have to be a cap. If you move that to runtime though then you can have your cake and eat it too, less the cost of compiling (i.e., bytecode generation) at runtime.
Etc. It's a tradeoff between binary size (which might have to be infinite in the compiled case) and runtime overhead (having to "compile" for each new kind of input you find).
morkalork•5mo ago
geokon•5mo ago
morkalork•5mo ago
https://medium.com/@davethomas_9528/writing-hello-world-in-j...