I love Java, I love the ecosystem. It's been a 25 year journey.
I will be the first to admit that I have not adopted "modern Java", mostly with all of the functional stuff (notably all of the collection streams and what not).
I certainly enjoy easy lambdas, but I don't necessarily code stuff up that way.
I'm not big on locked down classes, as a general rule. I won't say I never use "private", but it wouldn't bother me if that didn't exist. I can't say I'd "never" use records, but I'm so used to the boiler plate, I don't really see it any more.
My one issue, though, is simply how heavy handed the Java 9 module system is. I have a desktop app, and I use the module system to lighten up the JRE that it bundles. But that's an edge case (to me).
I'm just not a fan of it, I find it gets in the way more than anything, and it just seems more forced than optional.
Outside of building JREs, does anyone use the module system for anything?
My understanding is that the module system is primarily for library developers and not application developers. You can use the module system to strongly encapsulate your internals, which allows you to change those internal implementations without having to worry that some client is depending on it.
It’s for both really. The module system comes into play when application developers what to ship a jlinked runtime. You can make the size of your JVM executable down to like 35MB or smaller.
I don't see why it would be. The native image static analysis decides on the level of individual classes, methods, and even class fields what to include in the image and what not. It doesn't compile entire packages or modules into the image, only parts it considers reachable. And the module system shouldn't influence this reachability analysis I think.
Weird example with the "Java 8 exception handling":
catch (Exception e) {
if (e instanceof IOException) {
} else if (e instanceof SQLException) {
} else if (e instanceof NumberFormatException) {
} else {
}
}
Older Javas already allowed choosing which Exceptions (and subclasses) to catch directly.
The latest version of The Well Grounded Java Developer was released in 2022, when 17 was the latest LTS version. The high quality of that book and being able to prescribe it is one reason why someone might prefer it.
I think OpenJDK 17 might also the highest LTS installable one on Debian 12 out of the box right now, but that's a lot less certain.
As far as I'm aware, the only officially supported way of shipping Java applications is by building custom runtimes with jlink. So if you want to play by the rules, it doesn't matter what the distributions ship.
Ubuntu ships multiple runtimes for every supported distribution and does backports FWIW.
`jlink` was released for Java 9, I believe, so it's unlikely people who are upgrading from Java 8 already have the infrastructure in place to seamlessly transition to that instead of however they were managing their JAR files before.
"But this should be simple! It's almost like a Go binary!" I've learned not to underestimate how long it can take to change infrastructure. DevOps isn't seen as a profit center in most places, and they might well have much bigger things to worry about than transitioning from a kind of working JARs-on-VMs approach.
Jlink/jpackage UX isnt the best either. They mostly produce installers not a single binary that you can just run. Project Leyden has some interesting work around this called Hermetic Java which plans to ship one binary with the VM + jar together. It’s coming out of some folks at Google. I’m really looking forward to it.
Really now? Now that's interesting. I thought GraalVM might be a good option in that space https://www.graalvm.org/ last I checked, but something literally called Hermetic Java has my interest piqued.
If you're using AWS ElasticBeanstalk Tomcat distribution, 21 isn't supported yet. I realize this isn't a huge segment of the market, but it's probably not the only example.
The payment processing case is nostalgic if a bit ironic, the team I worked at used this exact pattern 6 years ago or so in C#, and the expressiveness has only improved since then.
Yes, C# is better by every measure and has had everything we can only dream of for decades. You can stop coming to every discussion of Java with the same old story.
It's tied to .NET at the hip - there are no 3rd party implementations (Mono is effectively dead, correct me if I'm wrong), it's development is effectively solely driven by Microsoft, and every few years you have to rewrite all your things or get stuck on EOL versions of frameworks or abandoned tooling. The community is also vastly different in that it does not (yet) value open source and many different implementations of ideas (ie. there's an official Microsoft way to do X and that's what everyone does).
C# might be a fine language, but it's coupling to .NET and Microsoft are kind of a liability.
Java has a ton of warts, and it's not the language I'd choose today. However, it's ecosystem is FOSS-first and is immense in size and scope, has numerous options for any type of library/framework (take a loot at HTTP clients, or logging frameworks, or web frameworks, etc), and while Oracle primarily drives development they don't get the de facto final say anymore. There's also many JVM implementations and many class library implementations - all with different pro's and cons.
Perhaps .NET will get there one day. It is, after all, relatively new at FOSS/XPlat.
At least the company driving .NET releases it under MIT and does not have a trap SDK that should you make a mistake of using makes your company liable to legal action by Oracle.
Surely you're not gonna say that OpenJDK and GraalVM (both owned by Oracle) is somehow an issue, would you? And Mono lives well in dotnet/runtime, serving targets like Browser WASM and iOS (until NativeAOT replaces it in full at that target, at some point).
But you're not using .NET, so no need to worry. No one is gonna pry Java from your hands, but we'll get to laugh at the choice - it is both slower in performance-oriented code and more verbose in LOB one. Pretty much the only driving reason behind choosing it is if the company is an Apache/Java shop or when a vendor offers an SDK in Java/Python/JS only due to their popularity which is a common issue in the industry.
There's dozens of JDK & Class Library implementations. If you use the Oracle one - well, that's on you.
Most people don't use the Oracle JDK anymore.
And OpenJDK is GPL licensed - and has no strings attached. What you are referencing are people using Oracle's First Party JDK (which has a base of OpenJDK + Secret Sauce). Oracle wants money for that.
> No one is gonna pry Java from your hands, but we'll get to laugh at the choice
I don't think anyone in Javaland are concerned. .NET usage is a tiny blip on the radar compared to Java/JVM ecosystem.
No, you don't need to pay for performance. The only people paying Oracle are those who choose to.
There are many JVM vendors - each with their own secret sauce, pros/cons and add-ons. Some charge to use, some charge for support, some just give it away. Almost all offer a for-free OpenJDK version as well.
Vendors include some of the biggest names in tech, such as Amazon and IBM, and many others you might only be aware of if you're in the ecosystem such as Eclipse Foundation, Azul Systems, Bellsoft, and more.
I would say the Oracle JDK/JVM is likely in the minority of JDK/JVM deployments today.
Oracle deliberately positioned themselves to be just another JDK/JVM vendor a few years back. All of the vendors can offer support etc. Oracle has no special control over OpenJDK these days, even if they pay the most full-time staffers to work directly on it.
Then what is the selling point of that, if you say crucial features are not closed-sourced and gated behind costly licensing?
I feel like this is among many other reasons that people get PTSD which causes them to throw the baby (C# of du jour bundled in public perception with Java) out with the bathwater (Java ecosystem) and move to, inferior in many ways, Golang.
The contribution graph says precisely what I claimed.
> Then what is the selling point of that, if you say crucial features are not closed-sourced and gated behind costly licensing
Each vendor can do what they want. As I have already said twice, some vendors give away their inhouse-built JVM/JDK and only charge for support, some charge to use it at all, and some just give it away entirely for free. Motivations for each vary by company.
The point is, you have a ton of choice within the JVM ecosystem. You have 1 choice for .NET... the ecosystem and community are not the same. The JVM ecosystem and community are vastly better by any measurement.
C# developer's only valid criticisms are levied at the Java language - failing to realize the slow development pace is deliberate and prevents people from having to rewrite everything every couple years...
Despite that, there are many languages that run on the JVM - so you don't even need to use Java to experience the greatness of the JVM ecosystem and community.
I'd rather not experience "the greatness of the JVM ecosystem and community" nor I have to rewrite code every two years, the only big break was ~8 years ago with .NET Framework -> FOSS .NET ordeal, all subsequent changes are minor and incremental and pretty much in the libraries only. In general, this view is unfortunate but not unexpected, and is common with Java or, for some reason, Go.
There's a world of different projects, beyond back-end applications, written in C# or even F# like games, scientific instrumentation and analysis, desktop and mobile applications (multi-platform or otherwise), trading systems, malware and anti-malware, and more. It's a really versatile and powerful tool.
Let's talk again when the project Valhalla is done and Panama vectors are actually usable for writing implementations that can compete with C++.
Many organizations are stuck on Java 8 because Java 9 made breaking changes. (Java 11 also made breaking changes.) Many of these changes also broke some popular libraries at the time that hacked into the JDK internals, so it meant a significant refactor for software that might be in maintenance mode already.
To clarify Java made changes to things they never promised would be a part of backward compatibility. Libraries were using things from JDK internals/implementation details, things that were never guaranteed to be there.
It isn't that severe of a break. Most of the friction was with the libraries with transitive dependencies, like ASM, that depend on a particular bytecode version, using internal classes that were removed (e.g. sun.misc.BASE64Encoder), or the new module system encapsulating APIs that were intended to be internal-only (usually fixable with JVM runtime flags.)
A lot of organizations that use Java are very conservative with their tech changes, and didn't see a compelling reason to upgrade. This was especially true since Android Java still used Java 8, so many popular libraries continued to support Java 8 for their Android userbase.
Java's version history crawled along at a snail's pace until Java 10, when they switched from a feature-based to a time-based release schedule. The release cycle has been pretty quick after that, since that happened only after 2017 or so.
That, combined with some pretty large changes in the underlying security model, mean that a lot of places have been stuck on Java 8 for a real long time. It's much harder to move from Java 8 to Java 9/10/11 in a lot of places than it is to then go from 9/10/11 to 17, for multiple overlapping tech debt cleanup reasons.
Try Kotlin. It's what modern Java should be, and might eventually slowly (slowly) develop into. It's a joy, and can use the entire JVM ecosystem (frameworks, libraries, tooling, etc).
The C# folks can't even knock it... it's less verbose and more functional.
Kotlin + Spring Boot for backend work is the way...
For boring line of business and crud applications there is almost no difference with latest versions of Java, and the feature gap closes with every release.
I recently finished (however much you can "finish" software) a project in Kotlin and probably won't be using it in the future. Compilation time, although much improved by recent releases, is still twice as slow as Java, you only get decent support for the language in IDEA (which makes sense since the officially stated goal of releasing Kotlin was to drive sales of their IDEs), and feature-wise the only thing it really has over Java is null safety, which is solvable through other means.
You get all the other problems of using a "guest" language (of which there have been many before — most of them long dead) like the disconnect between read-only data classes and records, which necessitates the use of @JvmRecord when you need specifically a record. This disconnect between the language and the JVM too will continue to widen.
> there is almost no difference with latest versions of Java, and the feature gap closes with every release
Java may be implementing features that Kotlin has had since day 1 (or close-to), but Java's syntax will always be what it is due to it's legacy. It's not "modern" syntax, and the way it handles fluent expressions will always be kludgey.
There is nothing special about Kotlin that required IDEA, other than it's convenient. Kotlin is a bundle of libraries and gradle plugins - so it can work on any IDE, including Eclipse or whatever you prefer.
Java's Optional is also much more kludgey than Kotlin's nullable types
Also, generally when writing Kotlin you don't need to make sure your code is interoperable with Java code - usually you are consuming Java code in your Kotlin code... so things like the suite of `@JVMxxx` annotations are not used. If you are writing a library or framework - then obviously concerns are different.
> but Java's syntax will always be what it is due to it's legacy. It's not "modern" syntax, and the way it handles fluent expressions will always be kludgey.
Good. If you're constantly learning something new about your language, there's something wrong with your language. There's 2 good ways to design a language: simple and powerful, or simple and simple.
Modern languages go for complex and powerful, which I personally dislike. Instead of building a simple but powerful language, they build special case upon special case until they have a powerfully complex language. The unfortunate thing is it's only powerful in the blessed ways, hence the complexity, rather than being generally powerful.
I really don't think a slightly different syntax is enough of an argument to bring a separate language, introduce another massive dependency (and another vendor) into your supply chain, and create additional problems with hiring people, but to each their own.
I don't mean Optional, it was never intended for widespread use, according to its own author. It's solvable by using annotations; uber has a solution that allows you to only annotate nullable fields, and the rest is assumed to be (and checked at runtime) as not null. There are never that many nullable fields in sanely designed applications.
Writing Kotlin in other IDEs is about as good as writing it in vim. Java experience is closer to the same level regardless of which of the big three (or two…) you prefer.
Thanks for naming Javalin - I had not previously heard of it and it appears quite nice.
I will say though, I vastly prefer pushing configuration out of my code and into config files/text. Things like `Javalin.create { config -> config.useVirtualThreads = true }` in my opinion should live in a config file.
But, to each their own - that's the beauty of the JVM ecosystem - lots of choice and lots of ideas.
Spring Boot pushes EVERYTHING into config. Whether annotations, or YAML files or property files or Gradle or Maven files or something else.
And those things are very very hard to debug. Java tools do not have an easy way to step through the code that gets executed due to you having an annotation in your source. Or the code paths that get executed to create beans and run code and generate entirely new classes with no source code...just by adding a dependency to your project.
For the things that really should be configuration, environment variables are perfectly fine.
This is an article about going from Java 8 to 17. Generics and annotations are from Java 5.
Java's implementation of generics isn't great, but there are some professional coders out there who were born after generics and annotations were added, so it's probably time to let that one go.
What's the motivation behind going to an article about a language upgrade, then proceeding to shit on language features that have been there even before Java 8?
Neither of your examples distinguish 8 and 17, and a few things highlighted in the article that do can only be said to make things simpler and easier, like records and text blocks.
I will be the first to admit that I have not adopted "modern Java", mostly with all of the functional stuff (notably all of the collection streams and what not).
I certainly enjoy easy lambdas, but I don't necessarily code stuff up that way.
I'm not big on locked down classes, as a general rule. I won't say I never use "private", but it wouldn't bother me if that didn't exist. I can't say I'd "never" use records, but I'm so used to the boiler plate, I don't really see it any more.
My one issue, though, is simply how heavy handed the Java 9 module system is. I have a desktop app, and I use the module system to lighten up the JRE that it bundles. But that's an edge case (to me).
I'm just not a fan of it, I find it gets in the way more than anything, and it just seems more forced than optional.
Outside of building JREs, does anyone use the module system for anything?