Java 22 Released(mail.openjdk.org) |
Java 22 Released(mail.openjdk.org) |
Finally solves the inscrutable Hello World program!
Yes, it's just ergonomics for early beginners. But could be the difference in whether or not someone new to programming sticks with Java or not.
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals...
I can only think the reason why they did this was to compete with python, as our scripting languages that do not require a main/Main entry point.
Personally, it just feels wrong for compiled-based languages.
I think they could improve on C# with their namespace. Rather, for example, a typical C# file looking like:-
using EFG;
namespace ABC
{
public class XYZ
{
}
}
They could just :- using EFG;
using namespace ABC;
public class XYZ
{
}
Pretty much taken from the C++ way.. but it saves on space availability.This solves the public static void main string args issue.
Still if I need JVM then Scala or Kotlin are still preferable over Java.
Obligatory Java for the Haters in 100 Seconds: https://www.youtube.com/watch?v=m4-HM_sCvtQ
That's so 2010. I would avoid Scala like plague. It is a soup of all features imagined and some more. Java is difficult for novice. With Scala even experienced senior devs can look into a snippet and be befuddled. It is designed by academicians who thought clever looking choice is better.
It's better to just say "we will come to this concept later", rather than make a fake syntax that does this (taken from the JEP) behind the scenes:
new Object() { // the implicit class's body }.main();
It adds more confusion, as you are left explaining that you could not really run an instance method without instantiating the class -- it was just something fake for beginners.
Compare that with Kotlin where you have top-level functions, so that `main` is just like any other function.
Console.WriteLine("Hello, world!") class MyClass {
{
System.out.println("Hello World!");
}
}
This will run when an object of the class is instantiated. So not useful for the case in question (you could get rid of the class declaration but would presumably still need a main method).(It's also pretty poor style, but occasionally useful in a pinch, like when instantiating an anonymous inner class, which has no constructors that take arguments)
It’s okay if you’re only writing a single file, and it really seems intended for beginners or micro applications, but for those of us writing anything besides the most trivial, it’s merely “cute” and just adds inconsistency.
System.out.println("Hello world!");Given these are still methods of classes this JEP seems pointless to me. Not having to write class x {} isn't a great time saver.
Or maybe we'll all move to Kotlin by then.
New and shiny syntax sugar becomes stale real quick.
For me personally the most interesting one is JEP461 (Stream Gatherers) https://openjdk.org/jeps/461
This will allow addition of interesting stream operations.
Even after nearly 30 years, Java is still a good choice to start something new (e.g. a startup).
- OpenJDK21: https://ports.macports.org/port/openjdk21/details/ , - openjdk21-zulu: https://ports.macports.org/port/openjdk21-zulu/details/ - openjdk21-oracle: https://ports.macports.org/port/openjdk21-oracle/details/
each of them having so many variants (see the links). What variant needs to be installed to just run a Java app?
If you want to just quickly run a fat jar then any will work. "openjdk21" is fine. The Zulu variant comes with JavaFX which simplifies things if your app needs that.
1. Applets ( Advertise the JVM capability "Applets".)
2.BundledApp ( Advertise the JVM capability "BundledApp". This is required by some java-based app bundles to recognize and use the JVM.)
3. JNI ( Advertise the JVM capability "JNI". This is required by some java-based app bundles to recognize and use the JVM.)
4. WebStart ( Advertise the JVM capability "WebStart".)
- what the heck? I think I am better off without Java. :)
Seven iterations? What is going on with vectors in Java?
Interop with iOS OTOH is a breeze, some of the APIs may require newer Swift Library Evolution ABI (direct calls to Swift exprots, without going through C/objC) but .NET is getting it in .NET 9 (the first and only platform to have it at the moment of release).
That said, you really need to write a bunch of boiler-plate to implement useful things in java-like paradigms in the library today. Just as an example, I wrote up a sane windows _getcwd() stub and it's like 30 lines to implement correctly (properly freeing the buffer when I'm down with it)
My pet project is to see if I can write automatic stubs around calls based on published API info and sources, so that at least some of that platform binding lift isn't just for those with non-trivial knowledge of C. Well, that's the hope anyways.
1. Pointers to the same (and not just references to objects).
2. Unions (via explicit-layout structs)
3. Function pointers.
4. C-style varargs.
To be fair, not all of these have been exposed in C# historically even though CLR had them all along. Most notably, unmanaged function pointers took over 20 years. And since most people look at CLR through the prism of C#, they aren't necessarily aware of these features.
Still, one way or the other, we're at the point where pretty much any C program can be transpiled to C# in a one-to-one mapping of almost every construct (setjmp/longjmp has to be emulated with exceptions), and a very similar performance profile of the resulting code.
However, I am a little concerned about the heavy emphasis on library unloading in the JEP. Unloading is famously fraught and unsafe for wide swaths of common libraries ... or maybe I'm overfitting due to recent trauma[1] and everything will be fine.
1. https://gist.github.com/thomcc/8c4a8003cf1a282949a539e899cb4...
But the ugliness of JNI stopped me. Then I tried FFI in Java 21, with jextract it was amazing.
I wasn't aware of FFI at first, but the finalized version of virtual threads made me check the Java release notes.
Part of the problem is the changes made between 8 and 17 could be incredibly disruptive depending on your libraries.
If they had stuck to not using sun.* stuff you were pretty safe, but a few very popular things did.
Then somewhere in there a lot of the common server stuff moved from javax.* over to jakarta.*.
Both were needed and very good, but could turn into dependency nightmares. So depending on your app/stack it wasn’t an easy transition.
17 is fantastic though, especially coming from 8. I’m excited about what’s already in 21 (latest LTS) and coming in the next LTS after that.
Java 8 is still under Extended Support until 2030 (and indefinite sustaining support). Java 11 left Premier Support September 2023.
"Java SE 8 has gone through the End of Public Updates process for legacy releases. Oracle will continue to provide free public updates and auto updates of Java SE 8 indefinitely for Personal, Development and other Users via java.com".
https://www.oracle.com/java/technologies/java-se-support-roa...
It wasn't ever part of the public API that's promised to never break, and JDK developers were annoyed that it being used meant Java got perceived as unstable, and it's gone in more recent versions.
As for the changes in 8->9, there was a stagnation period in the last year of Sun, and many people overfitted their libs to 8, by e.g. making use of internal APIs made accessible through reflection. This was never a good idea, and all that is happening now is that you have to explicitly state at invocation what kinds of non-future-proof modules you make use of, so that you are made aware of what could potentially change, plus it disincentivizes libraries from accessing these non-public APIs.
Snark aside, the problem with Java in the enterprise is that Oracle provides support for mind-bogglingly ancient versions (if you're willing to pay them). This disincentivizes companies from upgrading, ends up frustrating their developers, and has probably contributed to the negative reputation that Java has in some corner of the net.
I get that tracking the current version isn't feasible for most companies, especially if software isn't their core business. The Java folks do their best to make upgrades painless, but the longer you wait, the more painful it gets.
Java 8 keeps working, while "modern" Java keeps chasing mistakes like green threads. If anything, I'm more baffled by 9+ having a non-neglegible market share at all.
If by green threads you mean virtual threads in JDK 21 could you please elaborate why they are a mistake? I'm not a Java developer but from what I see new concurrency model allows to write much more efficient network software - OS threads are expensive (in terms of RAM/CPU) and to handle many thousands of network connections (C10k problem) you have to either throw a lot of hardware or use NIO (New/Non-blocking I/O) which is hard to code.
One of reasons why Go become popular - gorutines look like normal threads (relatively easy to code) but more efficient.
Even only considering JVM languages you run in to way too many options for the question in itself to be worth your time as a serious discussion.
IMO - use whatever you and your team like best and that suits your needs. Java is great for hiring new devs and is arguably the most well established in an enterprise settings.
If you want an actual answer: Personal preference.
I was hoping someone would answer with concrete technical tradeoffs and comparisons e.g. compile times, null safety, common footguns, personal experiences, etc.
I was recently asked for a comparison between Kotlin and modern Java by a team that's considering a migration of their legacy Java service. I haven't kept up with Java's changes, so didn't have an offhand unbiased comparison to share.
I've worked on backend Kotlin and Java codebases for the last five years and have introduced Kotlin to dozens of teams across my company. Nobody I've introduced Kotlin to has ever ended up preferring Java or switching back to it. There's been initial skepticism at first (reasonable), but after working in Kotlin for a week or two, I've seen even the staunchest Java devs proclaim they're never going back.
To the point on personal preference, I think it's a factor but I don't think it's _the answer_. It's a blanket statement that ignores important details. Languages have different affordances, features, paradigms, and patterns that lead you to develop and think in different ways. Some differences like null safe types are obvious improvements for a large codebase with many contributors. The feature catches real bugs and makes the system easier to build and maintain.
I think there's a lot of warranted skepticism of JVM languages that aren't Java, but something about Kotlin feels very different. For comparison, I've worked with Scala (Spark) and played around with Clojure in my free time.
I'm not sure what feels so much better compared to other JVM languages, but if I had to guess I'd say it's an emergent quality from a few things JetBrains has done really well. In particular:
- The 100% Java interop claim is real. I've only had minor hiccups with Lombok - The ability to incrementally adopt Kotlin in an existing Java codebase - The IDE support in IntelliJ IDEA is unbelievable. The suggested refactorings subtly teach you the language - Null safety lets you focus on domain modeling and business logic instead of error handling and validation - Kotlin's backwards compatibility. New versions never seem to break anything. And they even provide refactoring actions in IntelliJ to automatically update deprecated usages - Very few significant paradigm shifts. Kotlin doesn't force you to totally change your Java code to fit a functional style or anything like that. It just tries to make safer code easier to write - The political stability and longevity gained from Android's blessing as a first-class language makes Kotlin feel like more than just another JVM language. There's Kotlin running on billions of devices. That's a pretty big ship to turn around, sink, or replace
To summarize, Kotlin just feels like the elephant in the room. Aside from low-level changes like new FFI possibilities and GC improvements, it's not clear to me what value Java upgrades add in comparison to Kotlin—especially in regards to new language features and syntax.
Anyways, hopefully this followup post starts a more fruitful discussion. I asked this question in earnest based on my personal experiences and observations. If you haven't tried Kotlin yet, I'd suggest cracking open an IntelliJ scratch file and test driving it yourself.
That being said, the amount of rigor with which the JDK devs test their experiments is really something to witness. Its equivalent to old school MS with painstaking maintenance at backwards compatibility, all the while moving the wheel of progress.
Every single change so far has been planned with a decade of advanced planning because that's just how this ecosystem roles.
println("Hello world!")
I think that's as far as you can go.p = print # the print() function
# Now we can do:
p("Hello world")
# endlessly, in this file.
Shorter by 17-odd characters than the above Java version.
And the foothold in academics has some practical perks, too, like a sound type system (DOT calculus), compatibility guarantees at a theoretical level (TASTy), and what's cooking in the area of capture checking might be a general solution to many of the industry's biggest challenges (e.g. colorless asynchronous programming, safe errors, safe resource management, ... Think of Rust's borrow checker as a special case of this, and the consequences for scala-native as a systems programming platform).
That's just not true. That's the typelevel ecosystem. The official Scala toolkit mostly includes haoyi libraries which is pretty much Python like Scala.
So we're not getting "hello $name" but rather than STR."hello \{name}" they're now considering $"hello \{name}".
So once they actually settle on a design (which they seem to have closed on quite a lot in the last couple of years), it might not take that long to happen.
- triple-quote strings / blocks
- minimal class boilerplate (this posting)
- closures (Java closures are worse IMO)
- usable hashbang for UNIX
- I think java has strings in switch now, don't they? Do they have expressions?
WAIT, does Java STILL force you to write getter/setters?
switch on strings is there, as are switch expressions.
records now removes the need for getters in immutable contexts.
Java has the nullsafe operator now and the elvis too, doesn't it?
I don't use the spaceship operator much, implicit sorting works pretty well.
Groovy's closures have a lot less GOTCHAs. They simply work as expected, at least to me. Half the time I use java closures and I get complaints in compilation that I don't get in Groovy, but maybe they've improved closures more.
Groovy's GPars library is the bomb for concurrency/parallelism. I don't know if I could function in normal java constructs.
The .with keyword is a sneaky useful technique where you can declare a piece of data like:
"some cli command" .with { it.execute} .with { /* parse output */ }
It allows chained calls that flow naturally. Groovy generally allows pretty compact flowed calls which makes scripts a lot easier.
Groovy scripting with implicit vars is a lot easier than any java scripting, even with the "simplification" described.
The shorthand access/navigation of nested lists and maps, and the map / list literals (also taken by java at some point I think) are really nice to have. Also a + operator for lists and maps I use a lot
Groovy's ability to generically call methods without mucking through 10 lines of reflection is sometimes nice.
The auto-gen of getter/setters is a must have, I think Kotlin has those too?
CompileStatic lets me selectively use full java speed without groovy overhead.
In general, I like Groovy because it is typing-optional. Python and Javascript suck because they don't really have optional type enforcement. Java sometimes asks for too much typing. Groovy lets me select as needed.
The actual sane = for string assignment and == for sane string comparison is nice.
But honestly, Java with the listed features is a lot better. I'll probably still use groovy for doing what would normally done with bash (UGH) since I have a big CLI/scripting library base that handles argument parsing, json, encode/decode, encrypt/decrypt, zip/unzip, in nice compact syntax.
Groovy is basically a dead language now anyway. The world is overrun by JavaScript and Python, and AI looms to replace us all with horrid AI python or javascript glue code.
I was/am always glad to pay that tax because non-null-by-default and the vastly superior val/var keyword pairs are totally worth it but it for sure is not a drop-in replacement in team environments. I am already constantly battling the vscoders (to say nothing of vimers) whining that "IJ is too slow for my eeee-leeeet typin'"
If the language of the non-standard, deliberately ES262-incompatible NodeJS programming system (and GraalJS, for that matter) is called "JS" without anyone batting an eye—which it does—it's pretty silly to insist the language of Android isn't Java.
5. Stackalloc (C alloca), fixed buffers in structs and inline arrays
6. ref T and Span<T>, which act just like &mut T and &mut [T] in Rust (with the same syntax). They are used in both advanced and most basic APIs alike to provide zero-cost wrapping and/or slicing of arbitrary memory (managed heap, stack, NativeMemory.Alloc'd)
e.g. You can receive byte* and length from FFI and construct a (ReadOnly)Span<byte> from them. That span then can be passed to almost every method that used to work with arrays only during .NET Framework days.
It's a shame really that msft stewardship of the .net/clr was so lacking. Of all the modern virtual machine clr us pretty much up there
It's too bad that this vision was never fully realized - in part, because .NET was not open enough originally, but also because of internal divisions in Microsoft itself. If it did, we could have had the equivalent of both LLVM and WebAssembly much, much earlier.
Also why we got WinRT being like .NET, but with COM and C++, with .NET Native being a complete difference compiler toolchain, as he got hold of the Windows reigns.
We just have to go back in time and see all those Visual Studio.NET shows on surviving documents, or how Ext-VOS (what became .NET) was being done at MSR.
We could have had something like Android, Inferno/Limbo in terms of .NET usage across the Windows layers, but it always bumps into the love for COM and C++, which incendently is how many Longhorn ideas were remade in Vista and continues to this day, using COM instead of .NET.
Kotlin is only used on Jetpack Compose and a couple of AndroidX libraries, that you have to ship alongside the application. And as alternative to Groovy on Gradle build scripts.
I expect this year's GDC to announce Java 21 LTS support.
IMO those numbers create a lot of staying power for the language.
More like 70%, the remaining 30% are split between Linux kernel (C), Treble drivers written in C++ (Java is also supported), SQLlite (C), and naturally Skia, ART are written in C++. With a couple of newer drivers like the Bluetooth stack, adopting Rust.
However zero Kotlin.
Naturally Kotlin has such an adoption on userspace, Jetpack Compose the new UI framework is written in Kotlin, so already adopting that jumps up the adotption numbers.
It is like measuring Swift adoption by the use of SwiftUI, even if the business logic is still written in Objective-C.
I do agree that Google being Kotlin's godfather, pushing it for new projects, does create a lot of staying power.
However it is also the reason why on JVM, it is only yet another guest language, as there is no one telling Java developers they should not write Java to use framework XYZ.
All those that tried, Grails, Spark, Akka,... eventually lose adoption speed, and got replaced by Java alternatives.
Which Google had to accept, Kotlin's value without the breath of Java written libraries isn't that great any longer, and they aren't going to rewrite the whole Maven Central into Kotlin, as the Java community moves beyond Java 8.
Don’t forget traits! When are we getting traits in Java? Probably never.
Optional semicolons and parentheses to cut the line noise and enable internal DSLs.
Though Java has improved implicit typing with `var` and now we have reasonable lambdas, Java is still not a high-level language, but maybe it is now medium-high.
Well, yeah? Java's explicit strategy for the last few decades is to let other languages experiment, then implement the ideas that worked out once the dust has settled.
So we have to stick to OpenJDK which means 8 doesn’t receive security updates and is untenable.
Just for note, JDK 8 came from the same time as Windows XP. Sure, the attack surface is different, but if they have no plans on moving forward and doesn’t even want to pay for support, then frankly fck them. Then they just surprise pikachu when a bunch of their user data leaks.
We moved to the latest LTS. Continuing to use an old version with no security updates would be moronic. Of course we didn’t do that.
All I was saying was sticking with 8 wasn’t tenable for financial reasons.
Loom has a worse API, is hidden from the user (what's preemptible and what will cause OS thread starvation? who knows!), and effectively ends up infecting the whole JVM with its complexity.
Go shares most of those downsides, but as a greenfield project (..heh) there's at least the expectation that all libraries play nice with their scheduler. They also try to hide FFI starvation by effectively running each FFI call in a dedicated OS thread[0].
There's also gevent/greenlet, which tries to bolt "colourless" M:N scheduling onto Python. It hasn't exactly taken the Python world by storm either, despite being far older than their native asyncio support.
Overall, I'd consider all three implementations of the approach to be dead on arrival.
[0]: See https://stackoverflow.com/a/28356944, it's a bit obfuscated but the overall effect is the same
Also, Java has the luxury that almost no code makes use of FFI, so their impact is minimal.
Interesting point regarding scheduler and the interruptibility of FFI calls. Just thinking about it I don't see how this can be addressed. So definitely interested in learning here: what is the remedy to your criticism here beyond "document behavior"?
No, the JDK had builtin green-threads behind a command line flag around Java 1.1 on Solaris.
Does it? Preemptability is pretty robustly solved in Go. While it's sometimes less efficient than I'd like, it's a far cry from the initial draft of virtual threads in java where a misplaced "synchronized" could sneakily starve entire executors. Even with CGo pinning (which, as you indicate, is rare due to the bulk of pure-Go libraries) I'm having trouble thinking of reasonable situations where full starvation or deadlock occurs rather than (admittedly unpleasant!) latency and queueing.
That said, Loom is quite new and deliberately iterative in approach, and the Java core folks are quite skilled, so I do expect to see substantial improvements in behavior and issue-detection tooling here over the coming years.
> I'd consider all three implementations of the approach to be dead on arrival
I'd argue that eventlet/greenlet failed for different reasons than the concurrency model or starvation risk (the monkeypatching approach just can't sustainably work in an ecosystem as big and native-code-dependent as Python's), hence Python's falling back to traditional async/await cooperative concurrency.
The Rust folks are struggling with the same choices here as well, further constrained by their requirements of a GC-less runtime with near-zero-overhead C FFI, which precludes them from using Go's approach. There was some great discussion of that here: https://news.ycombinator.com/item?id=39242962
I get gradle is a disaster (but that's more of a poorly managed and evolved DSL problem)
But ... does anyone use Spock and think "groovy sucks"? Yeah, I doubt it.
Spock is also a DSL disaster that's trying to be ScalaTest (https://www.scalatest.org/user_guide/property_based_testing) but in a dynamic language. Every time I use it I have to re-learn the syntax. (I have the same issue with Gradle, so maybe it's just-me?)
If you want type safe SQL in particular, you can pry JOOQ out of my cold dead hands.
Scala is a dying language, anyone boarding that ship is making a mistake. Anyhow, I prefer Java supplemented with powerful features Scala doesn't have, such as type-safe SQL.
> If you want type safe SQL in particular, you can pry JOOQ out of my cold dead hands.
Jooq isn't bad, but it's not SQL, it's Java trying to be SQL. Manifold lets you write type-safe, native _SQL_ of any complexity directly in your code.
Especially that you call it a dying language, when it just got reborn, and better than ever with Scala 3.
Can you elaborate on this? I have been using JOOQ for years (with Kotlin), and I have never had any issues with it "trying to be SQL".
What? This site is getting worse by the day.
At the very least, I prefer not to have any surprises in my codebase because it looks like Java but isn't quite so really.
The vast majority of people that use it aren't, but that's a feature :)
Manifold isn't an all-or-nothing proposition. It's architecture is modularized so that you can select the parts you want à la carte as separate dependencies in your build.
> At the very least, I prefer not to have any surprises in my codebase
But manifold surprises are pleasant ones :) As with any library or framework, it's a design decision: does it provide enough productivity and opportunities to offset its presence in your project? It's not a panacea.
Oh that's neat! Didn't sound like it when I was skimming over it. I'll keep it in head next time a pet project comes along :-)
A "DSL" like SQL that you use hundreds of times a year you'll learn the model of.
A DSL like groovy that you use once for project setup (and for that you'll one-off it likely and stackoverflow the rest of the question) is not. And it isn't really natural, it's a bunch of arcane steps that at the end might superficially look a bit consistent, but still really isn't.
Groovy really needs an autocompleter or a generator. Or, well, as you say, you stackoverflow for everything outside the very vanilla basics of it.
But good luck getting the right version match to the syntax you need. Christ.