ThursdayWednesdayTuesdayMondaySundaySaturdayFriday

Java at 30: Interview with James Gosling

chhum 251 points thenewstack.io
exabrial
Java performance isn't the fastest, that's ok, a close 3rd place behind C/CPP ain't bad. And you're still ahead of Go, and 10x or more ahead of Python and Ruby.

Java syntax isn't perfect, but it is consistent, and predictable. And hey, if you're using an Idea or Eclipse (and not notepad, atom, etc), it's just pressing control-space all day and you're fine.

Java memory management seems weird from a Unix Philosophy POV, till you understand whats happening. Again, not perfect, but a good tradeoff.

What do you get for all of these tradeoffs? Speed, memory safety. But with that you still still have dynamic invocation capabilities (making things like interception possible) and hotswap/live redefinition (things that C/CPP cannot do).

Perfect? No, but very practical for the real world use case.

brightball
When I got out of college and was still firmly in the "Java is the solution to everything" mentality I didn't realize that my admiration was really for the JVM and the Java App Server tooling that was so much more advanced than anything else at the time. It was basically Docker + K8s for anything running on the JVM more than 2 decades earlier.

Java the language eventually drove me away because the productivity was so poor until it started improving around 2006-2007.

Now I keep an eye on it for other languages that run on the JVM: JRuby, Clojure, Scala, Groovy, Kotlin, etc.

IMO JRuby is the most interesting since you gain access to 2 very mature ecosystems by using it. When Java introduced Project Loom and made it possible to use Ruby's Fibers on the JVM via Virtual Threads it was a win for both.

Charles Nutter really doesn't get anywhere close to enough credit for his work there.

cogman10
Let me extol the virtues of Java the language.

You can take pretty much any code written for Java 1.0 and you can still build and run it on Java 24. There are exceptions (sun.misc.Unsafe usage, for example) but they are few and far between. Moreso than nearly any other language backwards compatibility has been key to java. Heck, there's a pretty good chance you can take a jar compiled for 1.0 and still use it to this day without recompiling it.

Both Ruby and Python, with pedigrees nearly as old as Java's, have made changes to their languages which make things look better, but ultimately break things. Heck, C++ tends to have so many undefined quirks and common compiler extensions that it's not uncommon to see code that only compiles with specific C++ compilers.

jsight
Yeah, that and the portability are really incredible and underrated. It is funny, because I constantly hear things like "write once, debug everywhere", but I have yet to see an alternative that has a higher probability of working everywhere.

Although Python is pretty close, if you exclude Windows (and don't we all want to do that?).

cestith
I can run basically any Perl code back to Perl 4 (March 1991) on Perl 5.40.2 which is current. I can run the same code on DOS, BeOS, Amiga, Atari ST, any of the BSDs, Linux distros, macOS, OS X, Windows, HP/UX, SunOS, Solaris, IRIX, OSF/1, Tru64, z/OS, Android, classic Mac, and more.

This takes nothing away from Java and the Java ecosystem though. The JVM allows around the same number of target systems to run not one language but dozens. There’s JRuby, Jython, Clojure, Scala, Kotlin, jgo, multiple COBOL compilers that target JVM, Armed Bear Common Lisp, Eta, Sulong, Oxygene (Object Pascal IIRC), Rakudo (the main compiler for Perl’s sister language Raku) can target JVM, JPHP, Renjin (R), multiple implementations of Scheme, Yeti, Open Source Simula, Redline (Smalltalk), Ballerina, Fantom, Haxe (which targets multiple VM backends), Ceylon, and more.

Perl has a way to inline other languages, but is only really targeted by Perl and by a really ancient version of PHP. The JVM is a bona fide target for so many. Even LLVM intermediate code has a tool to target the JVM, so basically any language with an LLVM frontend. I wouldn’t be surprised if there’s a PCode to JVM tool somewhere.

JavaScript has a few languages targeting it. WebAssembly has a bunch and growing, including C, Rust, and Go. That’s probably the closest thing to the JVM.

dotancohen

  > I can run basically any Perl code back to Perl 4 (March 1991) on Perl 5.40.2 which is current.
Yes, but can you _read_ it?

I'm only half joking. Perl has so many ways to do things, many of them obscure but preferable for specific cases. It's often a write-only language if you can't get ahold of the dev who wrote whatever script you're trying to debug.

I wonder if modern LLMs could actually help with that.

fuzztester
Yes, but can you _read_ it?

Java was marketed (at least in its early days) as a WORA language - WRITE ONCE RUN ANYWHERE.

Perl was unmarketed as a WORM language - WRITE ONCE READ MANY (TIMES). ;)

jk, i actually like perl somewhat.

but I think Larry and team went somewhat overboard with that human-style linguistics stuff that they applied to perl.

cestith
I can. Some of it by some developers I can read far more easily than others.

Can you read arbitrary code written by developers from around the world in PL/1, or Ada, Forth, APL, or even C++? Big languages have lots of syntax choices, yes. It doesn’t need to be abused.

Even C has an obfuscated code contest that’s been going on for decades.

johnisgood
I wonder if modern LLMs could actually help with that.

From experience, they can.

vram22
Interesting about that long list of languages.

There's also Groovy.

I wonder what other languages run on the JVM. What about Perl, Icon, SNOBOL, Prolog, Forth, Rexx, Nim, MUMPS, Haskell, OCaml, Ada, Rust, BASIC, Rebol, Haxe, Red, etc.?

Partly facetious question, because I think there are some limitations in some cases that prevent it (not sure, but a language being too closely tied to Unix or hardware could be why), but also serious. Since the JVM platform has all that power and performance, some of these languages could benefit from that, I'm guessing.

#lazyweb

cestith
I mentioned Haxe by name, and Eta is essentially Haskell on JVM.

There is an OCaml-Java. NetRexx targets the JVM. For Prolog there are JIProlog and TuProlog at least.

Red basically is REBOL. Yes, Red targets IA-32, ARM, JVM, AVM2, x64, and the CLR.

I’ve seen some experiments for running Perl on the JVM. Rakudo can target the JVM for Raku, which is Perl’s sister language.

For Ada, gnat can target the JVM. https://docs.adacore.com/gnatvm-docs/jgnat_ug.html

For Forth there are a number of implementations. JVMForth, jForth, Misty Beach Forth, HolinJ Forth, bjforth, and xforth at least.

I’ve seen a couple different Java libraries for SNOBOL-style matching but I’ve never seen a SNOBOL tool that targets the JVM.

MUMPS has M4J.

Rust is interesting. There are JVMs written in Rust. There’s support for the JNI for Rust for interoperability. I’m not aware of a JVM target for Rust, though. However, Rust still uses LLVM as its primary code generator. As I mentioned, there are LLVM IC to JVM compilers.

Basic isn’t really a single language. For something like MS Visual Basic, there’s Jabasco. There’s JVMBasic. MBC transpiles Basic to C or C++, so you could use clang to put its output on the JVM. PuffinBASIC is a Basic interpreter written in Java. GLBasic compiles to C++, so again with LLVM all things are possible here. BCX Basic also outputs C or C++. There’s something just called “BASIC Compiler” that is both written in Java and compiles its source to JVM bytecode. The basgo compiler outputs Go code, so anywhere you can target golang code you can target Basic code with basgo, including the JVM. I’m sure there are a lot more. These are different versions of Basic on the source side, some of them similar to one another.

Nimlvm is a Nim compiler to LLVM intermediate code. So once again, as a chain of steps it can be done.

Speaking of chaining translators/transpilers/compilers, did I mention there’s a WebAssembly to JVM compiler? There are actually more than one. Chicory is one and asmble is another. There’s something called “Happy New Moon with Report”. There’s also a WASM written in Scala called Swam. I’m sure I’m missing some.

So the huge and growing list of languages that target WASM can also be chain-translated to target the JVM. That includes C, Rust, Nim, TypeScript, C++, Forth, Go, F#, Lua, Zig, and more. https://wasmlang.org/

So if it targets the JVM, it can run on the JVM. But also if it targets WebAssembly, C, C++, LLVM IC, Lua, Go, and more it can also through other tools target the JVM. Or if it has an interpreter that runs on the JVM because it’s written in Java, Scala, Clojure, or some other language you can get it there. If you really want to get exotic and esoteric, there’s an x86 emulator in WASM out there and you could probably run that on one of the JVM WASM interpreters.

dmit
Haskell

https://github.com/Frege/frege

https://github.com/typelead/eta

Of the others you mentioned, I bet there's a couple JVM Prologs out there, but haven't encountered any myself.

sigzero
I can run THE SAME CODE on DOS, BeOS, Amiga, Atari ST, any of the BSDs, Linux distros, macOS, OS X, Windows, HP/UX, SunOS, Solaris, IRIX, OSF/1, Tru64, z/OS, Android, classic Mac, and more.

No, you really can't. Not anything significant anyway. There are too many deviations between some of those systems to all you to run the same code.

maxlybbert
Honestly, the main difference I run into is just file paths, and that’s easy to sidestep ( https://perldoc.perl.org/File::Spec ).

There are differences, but they’re usually esoteric ( https://perldoc.perl.org/perlport#PLATFORMS ).

cestith
Yes, I really can, and with the same number or fewer OS-specific checks than the equivalent C program.
bhaak
I often run into problems running Python code under Linux.

I don’t know if it is a me problem or if I’m missing the right incantations to set up the environment or whatever. Never had that much problems with Java.

But I’m a Java and Ruby person so it might really be missing knowledge.

kevin_thibedeau
It's not you. Python packaging has regressed into a worse mess than it was 20 years ago. I limit myself to simple scripts that only rely on builtins. Anything more complicated goes to a more dependable language.
icedchai
I rarely run into issues when using Poetry. If you use pip, add packages to requirements.txt willy-nilly and don't pin versions then you are asking for trouble.
myko
i like poetry though i've moved to uv - both work really well
bornfreddy
I use pipenv and it kind-of-works. Will try uv or poetry though - which one would you recommend?
dwood_dev
UV. Using it as the exec target for python (UV script) is great. Dependencies declared at the top, now I have executable files in something better than bash.

I no longer shy away from writing <500 LOC utility/glue scripts in python thanks to uv.

myko
I can't recommend uv enough. It's so fast, and uvx is so useful to run a random Python CLI tool. If you want to do things like you're accustomed to with pip you just `uv pip ...`
icedchai
I've heard great things about uv. I plan to try it for my next project.
LtWorf
Poetry doesn't fix the fact that python removes modules from the standard library every release.
icedchai
I've never run into that.
LtWorf
Doesn't mean the problem doesn't exist.
fuzztester
I don't know about the difference between 20 years ago versus now, but it's certainly doesn't seem to be clear now.

e.g. poetry, venv and pyenv have been mentioned in just the next few comments below yours. and this is just one example. i have seen other such seeming confusion and different statements by different people about what package management approach to use for python.

fuzztester
what languages do you use for the latter?
cestith
Python can be tricky with the big differences between 2 and 3.
loloquwowndueo
Python 3 came out in 2008. If the 2 vs 3 differences are still biting you you probably have bigger problems to solve (deprecated, insecure, unmaintained dependencies for example).
coolcase
And IPv6 came out in 1995
loloquwowndueo
Your point?
coolcase
"Comes out" and "Ready to switch to" are two different things.

Your conclusion is correct but not because Python 3 came out in 2008. It was ready to switch to some point a few years later but we'll before 2025 (I don't recall when sorry I didn't do Python at the time!)

icedchai
As late as 2022, I was at a company still in the middle of "migrating" from 2 to 3. I wouldn't be surprised if the migration project was still going on. The system had gone beyond tech debt and was bordering on bankruptcy.
jsight
Honestly, it isn't just you. I had to hold off on 3.13 for quite a while too, because of various package conflicts. It isn't terrible, especially thanks to things like pyenv, but it is far from perfect.
jonhohle
For anything more than just a one off script, look into venv. I’ve not written any python until this past year and can’t imagine maintaining an ongoing project without it.

Prior to that I would frequently have issues (and still have issues with one-off random scripts that use system python).

invalidname
I just spent 30 minutes trying to get a python package running on my Mac... Not feeling that. Pythons version compatibility is just awful and the mix of native is deeply problematic. Don't get me started on tooling and observability.
KronisLV
Moreso than nearly any other language backwards compatibility has been key to java.

The Java 8 and 8+ divide very much works against this. It was a needed change (much like Python 2 vs 3) but nowhere near pleasant, especially if some of your dependencies used the old Java packages that were removed in, say, OpenJDK 11.

Furthermore, whenever you get the likes of Lombok or something that has any dynamic compilation (I recall Jaspersoft having issues after version upgrade, even 7 to 8 I think), or sometimes issues with DB drivers (Oracle in particular across JDK versions) or with connection pooling solutions (c3p0 in particular), there's less smooth sailing.

Not to say that the state of the ecosystem damns the language itself and overall the language itself is pretty okay when it comes to backwards compatibility, though it's certainly not ideal for most non-trivial software.

cogman10
The Java 9 change was to remove access to unofficial APIs.

I agree it was somewhat painful, but not nearly to the level of the 2->3 change which ended up changing python syntax. Most dependencies worked throughout the change and still work.

Furthermore, whenever you get the likes of Lombok or something that has any dynamic compilation ... there's less smooth sailing.

Not sure about c3p0, but Lombok goes out of it's way to inject itself into javac internals in order to make it's output changes. It's using the most internal of internal code in order to make that @Getter annotation work. Plenty of other annotation processing APIs are completely unaffected by javac updates because they choose not to use internal APIs. Immutables, Autovalue, dagger2, all examples of dynamic compilation that continue to work regardless the version of java. Lombok is a horrible little dependency that I wish people would abandon. It's making a mess and then complaining that it's somehow Java's fault because Lombok decided it needed access to the AST.

I get it, things have broken. But what has been broken is literally the undefined and non-public APIs which went so far as to call their packages things like `sun.misc.unsafe` just to try and ward off people from using these APIs. (With the javadocs to boot which told people not to use this).

And even with the break, the Java devs went out of their ways to make stand-in apis.

brightball
That is an excellent point too.

It always made me wonder why I hear about companies who are running very old versions of Java though. It always seemed like backwards compatibility would make keeping up to date with the latest an almost automatic thing.

fpoling
Java version updates typically change GC behavior. If one has highly tuned setup there is no guarantee that a newer version would not regress.

Another problem is crashes. Java runtime is highly reliable, but still bugs happens.

Pet_Ant
Are you talking about performance or behaviour? I’ve never seen an issue caused by a GC.
fpoling
Latency spikes are the issue. Modern Java mostly solved this, but tuning GC settings is still the thing especially when Java runs on a big server.
josefx
It is "mostly" backwards compatible. Applets and everything related to them where dropped. A few interface dependencies where changed to improve modularity of the runtime. Widely used hacks like sun.misc.unsafe are getting replaced with official APIs and locked down. Development of some Java EE packages has been taken over by a third party, so they are no longer packaged within the java namespace. To name just a few of the bigger examples.
kamma4434
It is - but you don’t want to find out that something broke because of odd JVM update. If it ain’t broken…
AnimalMuppet
That's not the virtues of Java the language. That's the virtues of Java the backward-compatible platform. That is, you didn't say anything about the language (syntax and semantics), you only talked about backward compatibility.

(It's still a valid point. It's just not the point you labeled it as.)

cogman10
The language also follows the backwards compatibility principles. Java hasn't, for example, added new keywords in a backwards incompatible way. You can, for example, have something like

    int record = 1;
    double var = 2;
even though `var` and `record` are now used to create and define things.
eppp
I know that what you said is supposed to be true. However in my real world experience it is anything but. Cisco java programs are a disaster and require certain JVMs to run.
aaronbaugher
The enterprise Java applications we use require specific versions of specific Linux distros. It's possible that they would run on other distros, or even other operating systems, if you got the right JVM. But there's enough question about it that the companies that sell them for a substantial price aren't willing to promise even a little portability.
thomashabets2
I have the exact opposite experience. I haven't coded much Java, but when I tried to revisit it, code I wrote 10 or 20 years ago doesn't even remotely compile anymore. While with C++, 20 years later you may need to add a missing #include (that you were always supposed to have), but then it just works as it always has.

Java is, in my opinion, a complete mess. And I think it's weird how anybody could like it past the 1990s.

C++ not being compilable later hasn't been true since pre standard C++. We're talking 1980s now.

https://blog.habets.se/2022/08/Java-a-fractal-of-bad-experim...

fpoling
I have C++ code from 1997 that I occasionally compile. So far it runs. 10 yeas ago compiling with -Wall exposed an inconsequential bug and that was it. I suspect when it stops to compile it will be from an absence of a particular X11 library that I used to parse a config in otherwise command-line utility.

Which also points to another thing where Java compatibility shines. One can have a GUI application that is from nineties and it still runs. It can be very ugly especially on a high DPI screen, but still one can use it.

int_19h
The counter-example to this is C#. Barely younger than Java (by 5 years), and starting its life as mostly a Java clone with a sprinkle of Delphi, it evolved much faster and made many changes which "make things look better" without breaking things. Source-level compatibility goes pretty much all the way back to 1.0, as well.
worik
I have been badly burned, twice, by Python's cavalier attitude to backwards compatibility
vaylian
Python "the language" or Python "the ecosystem"?
worik
The language?

I am a mere user. I have two Python based systems that worked in Debian 11 and not in Debian 12

Python 3.9 to 3.11 I think was the change.

A

cbm-vic-20
I've got a jar that does one small thing and does it well that was compiled in 1998. Still works fine, no reason to update it.
johnisgood
You can take pretty much any code written for Java 1.0 and you can still build and run it on Java 24.

This is not my experience with Java at all. I very often have to modify $JAVA_HOME.

winrid
Are you using Gradle projects? Gradle is especially difficult for some reason.
johnisgood
Sadly. I would rather avoid Gradle and Java in general. I did not have good experiences with them. :/
jbverschoor
Oh yeah. I still don’t understand why we even moved away from the original JEE model, including the different roles (app dev, deployed, etc).

The whole spec was great with the exception of entitybeans.

It provided things that are still not available it anything else.. why do we store configuration/credentials in git (encrypted, but still).

And the context were easy to configure/enter.

Caucho’s resin, highly underrated app server. Maybe not underrated, but at least not very well known

icedchai
Entity Beans were terrible, representing the height of JEE over complexity. I remember editing at least 3 classes, a couple interfaces, and some horrific XML deployment descriptors to represent an "entity." A lot of the tooling was proprietary to the specific app server. On top of that, it was slow.

In the early 2000's, I used to work on JEE stuff for my day job, then go home and build PHP-based web apps. PHP was at least 10x more productive.

zmmmmm
The worst thing about EntityBeans is they were so bad they made Hibernate look good, which led people to think it was good. After 10 years of hammering against ORM complexity I finally switched to using thin database wrapper layers and have not once ever regretted it.
jbverschoor
I you just wanted queries, entity beans were ok.

Just a lot of boilerplate code, but the overal architecture and structure of JEE is still very sound

icedchai
A lot of boilerplate and XML hell!

What did you like about JEE? I worked in that world for years and don't miss it in the least.

jbverschoor
You know what's funny? Spring (earlier versions) had even more xml ;-)

I dunno it just worked for me. But I kept using the standards, no vendor lockin stuff, which bea etc always wanted.

I think the servlet design is great, the whole packaging/deployment model is great. And then well the session beans were overkill in general, so they were swapped out quite early by me. Swapped jsp out for I think velocity templates. And that application is still alive, running, and on the same platform.

And Java meant, at least for me and how I configured it, proper debugging and IDE support (love Eclipse), hot code reload, easy releases, repeatability, ci/cd. The last 20 years, no __significant__ improvements in my opinion.

icedchai
I think servlets are great, too. Coincidentally I also swapped out JSP for Freemarker and then Velocity templates pretty early. The session beans and entity beans I could both live without. The "heavy weight" nature of the commercial app servers really bothered me. JBoss was fine, but WebLogic, WebSphere, etc were awful.
icedchai
Yes! Hibernate was awful, but still light years ahead of EJBs. I worked on a couple of Hibernate projects and always left asking why...
jbverschoor
I never had any trouble with Hibernate tbh. It allowed you to drop back to raw sql if needed, and also custom fields to select if needed.

I never understood the fight against ORMs. In the end you'll simply be writing your own framework

int_19h
Only if you insist on a nearly 1:1 mapping between your data and your class hierarchy.
grandiego
Hibernate... a real PITA every time the application needed something beyond basic single-table CRUD queries; sadly for me it happened 99% of the times. After some months of torture, plain JDBC with their stupid checked exceptions was refreshing, even without wrappers.
xienze
You have to keep in mind that entity beans were developed in a time before generics, annotations, and widespread use of byte code enhancement that made a lot of the easy, magical stuff we take for granted possible.
icedchai
I remember. During the same time period, I wrote some Java apps that used plain old JDBC, plus some of my own helper functions for data mapping. They were lighter weight and higher performance compared to the "enterprise" Java solutions. Unfortunately they weren't buzzword compliant though.
brightball
I remember Resin.

I grew to be a big fan of JBoss and was really disappointed when the Torquebox project stopped keeping up (Rubyized version of JBoss).

datavirtue
Yeah, JBoss put "it's slow" to bed right away. I was doing my own research at the time and tried some workloads on it. Huge difference.
liveoneggs
resin was okay but I never got what it offered over tomcat
jbverschoor
Full JEE, not just servlets, performance, reloading, and a bunch of enterprise features. Resin existed.

After about 10+ years Spring kind of took over JEE.

Omg. Spring was just like moving code to xml. Different now, but still.

What I miss from JEE:

- single file ear/war deployment, today that’s a docker image

- the whole resource api from Java (filesystem/jar doesn’t matter). It means you don’t necessarily have to unpack the jar

- configuration / contexts for settings, + UI for it, database connections etc. Docker kind of works, most most images fail to achieve this. Docker compose kind of takes care of things.

- as said before.. all Java still runs everywhere

ksec
It is unfortunate the whole JRuby doesn't get more attention and it seems Rails community dont use JRuby much.

JRuby could also run on Graal as well.

hintymad
And hey, if you're using an Idea or Eclipse (and not notepad, atom, etc),

Java's tools are really top notch. Using IntelliJ for Java feels a whole new different world from using IDEs for other languages.

Speaking of Go, does anyone know why Go community is not hot on developing containers for concurrent data structures? I see Mutex this and lock that scattering in Go code, while in Java community the #1 advice on writing concurrency code is to use Java's amazing containers. Sometimes, I do miss the java.util.concurrent and JCTools.

zwnow
Just implement concurrency with actors and u save up on some locks and mutexes...

The patterns are available, its up to the community to apply proper concurrency patterns.

PaulDavisThe1st
The only replacement for locks/mutexes is a lock free data structure. Locks are not what make concurrency possible, they are what makes it data-safe.

You can use platform threads, user-space threads, language-provided "green" threads, goroutines, continuations or whatever you wish for concurrency management, but that's almost orthogonal to data safety.

MaxBarraclough
I'm not sure what you mean here, as far as I'm aware data safety isn't standard terminology.
lazide
I think they’re using it in the context of what you’ll get without some degree of locking, which is data corruption and/or other issues.

It’s not that you need locking to use threads. You need locking to stop threads from ruining any shared resource/data they are both trying to touch at the same time.

saagarjha
Actors are implemented using locks.
pimeys
Is it really so? I haven't checked all the implementations, but my take here would be to use a channel with atomics instead of a lock...
saagarjha
It's probably possible to do if you think about it carefully but generally enqueuing a message is going to take a lock, especially if you can send an arbitrary number of messages (which may require the queue to be reallocated).
pimeys
One very common queue implementation you can use to implement actors is the crossbeam-deque. It's work-stealing in nature, works in multi-threaded environments and has no locks. The implementation is quite simple to follow:

https://github.com/crossbeam-rs/crossbeam/blob/master/crossb...

yubblegum
One very common queue implementation you can use to implement actors is the crossbeam-deque

I can't find any references to a "crossbeam dequeue" outside of Rust sources. Is this a neologism for a "very common" pattern, or just very common in Rust?

steveklabnik
crossbeam is a package name. It would be like googling “Nokogiri XML” and only getting Ruby results.

The generic name is just Deque. https://en.wikipedia.org/wiki/Double-ended_queue

yubblegum
Thanks.
saagarjha
Oh, interesting. Ok I take back my claim then.
surajrmal
Note that the mpsc queue in the rust stdlib is also a clone of crossbeam and therefore also lockless.
paulddraper
The x86 instruction set is available as well.
eikenberry
It's a core principle.

    Don't communicate by sharing memory; share memory by communicating.
The overuse of Mutex and Lock are from developers bringing along patterns from other language where they are used to communicating via shared memory. So this aspect of the language just doesn't click as well for many people at first. How long it takes you to get it depends on your experience.
fidotron
My experience is a shocking amount of the golang community believe channels are a performance problem for whatever they're doing, and they use mutexes in some misguided effort at optimization.

But then I have also encountered Rust people that will look down on Java but had no idea buffered I/O had higher throughput than unbuffered.

surajrmal
Depending on the situation, channels can absolutely be higher overhead and not worthwhile. Google internally recommends not using them in many situations.

Unbuffered IO is a tradeoff. For certain use cases it does help, because throughput isn't everything. I'm sure Buffered is better in the average use case, but that doesn't mean you would never need unbuffered.

fidotron
Depending on the situation, channels can absolutely be higher overhead and not worthwhile.

Like streaming arrays one byte at a time through the channel.

Such devs just aren't very good, and hear "Google internally recommends not using them in many situations" but jump to inferring that means all of their situations qualify.

but that doesn't mean you would never need unbuffered.

Note that this was never claimed.

surajrmal
Channels make the most sense when you need to decouple code. The performance differences rarely are a bit deal. Most of the time it's unnecessary cognitive overhead. People treat both sides as dogma, but the truth is that you need to be think critically when choosing between the two.
hintymad
Thanks! What about data structure shared by multiple goroutines? Say, an in-memory cache object? Or do we always have multiple goroutines talk to a dedicated goroutine for the shared value? Would the performance be okay for all use cases? A reason that people use JCTools is that it can easily support hundreds of millions of concurrent reads/writes to its data structures on a 10-year old laptop.
eikenberry
For things like cache I generally have 2 goroutines communicating with it. One that directs reads and one that directs writes. Using CSP style you can pass the data (by value) through to the cache (or any other CSP style process) without copying and it performs quite well. I've written several high performance systems in this way with great results.
shanemhansen
I'll offer a counterpoint to the responses. Until go got generics, concurrent data structures were awkward. The stdlib now does include things like sync.Map.

In fact my experience has been that overuse of channels is a code smell that alot of new go developers fall into and later regret. There's a reason the log package uses a mutex for synchronization.

In general I think channels are great for connecting a few large chunks of your program together. Concurrency is great but also not every function call benefits from being turned into a distributed system.

I think that it would be a great idea to develop more concurrent go data structures with generics and I suspect inertia is what's keeping the community from doing it.

My credentials such as the are: been writing go since 1.0. worked at Google and taught go classes as well as owned some of the original go services (the downloads server aka payload server).

hintymad
Yeah, even with channels and goroutines, I’d imagine we can encapsulate them as primitives in containers like concurrency literatures often advocate. Case in point, it was fun to go through Pike’s talk Go Concurrency Patterns, yet I’m not sure all the patterns he discussed in the talk would be that simple to implement compared to just declaratively using well-packed containers
int_19h
Not just generics, but also a way to generalize iteration (i.e. the equivalent of Java iterators). Which Go has only got even more recently than generics.
znpy
Java memory management seems weird from a Unix Philosophy POV, till you understand whats happening. Again, not perfect, but a good tradeoff.

The GC story is just great, however. Pretty much the best you can get in the entire ecosystem of managed-memory languages.

You have different GC algorithms implemented, and you can pick and tune the one that best fits your use-case.

The elephant in the room is of course ZGC, which has been delivering great improvements in lowering the Stop-the-world GC pauses. I've seen it consistently deliver sub-millisecond pauses whereas other algorithms would usually do 40-60 msec.

Needless to say, you can also write GC-free code, if you need that. It's not really advertised, but it's feasible.

neonsunset
Needless to say, you can also write GC-free code, if you need that. It's not really advertised, but it's feasible.

It is not feasible under the JVM type system. Even once Valhalla gets released it will carry restrictions that will keep that highly impractical.

It's much less needed with ZGC but even the poster child C# from the GC-based language family when it comes to writing allocation-free and zero-cost abstraction code presents challenges the second you need to use code written by someone who does not care as much about performance.

zdragnar
Zero-allocation (obviously different from zero GC) frameworks made a bit of a splash a little while back, but I'm not seeing much about them anymore from a brief search. I would have sworn that quarkus was one of them, but it looks like that's definitely not the case anymore.

The downside is that you sacrifice a lot of the benefits of guard rails of the language and tooling for what may not end up being much savings, depending on your workload.

znpy
The downside is that you sacrifice a lot of the benefits of guard rails of the language and tooling for what may not end up being much savings, depending on your workload.

I think that's mostly done in organisation where there's time, budget and willingness to optimize as far as possible.

Sacrificing the guardrails doesn't make sense for the "general public" software but does tremendous sense in environment where latency is critical and the scale is massive. But then again, in those environments there are people handsomely paid to have a thorough understanding of the software and keep it working (making updates, implementing features etc).

I worked on a software that was written to be garbage-free whenever it could. Latency (server-side latency, i mean) in production (so real-world use case, not synthetic benchmark) was about 7-8 microseconds per request (p99.9) and STW garbage collection was at around 5msec (G1GC, p50, mostly young generation) or ~40 msec (p99.9, full gc) and was later lowered to ~800-900 microseconds with ZGC.

I know it might sound elitist but the real difference here are... Skill issues. Some people will just shun java down and yap about rewriting in rust or something like that, while some other people will benefit from the already existing Java ecosystem (and tooling) and optimize what they need to get the speed they're targeting.

I know I'll be downvoted by the rust evangelism task force, but meh.

zdragnar
Is data access in such a project purely from in-memory sources? I suspect most people shun it because database access- especially if the DB itself is over the network on a different machine- already slow enough that ZGC / zero allocation won't be noticed.
znpy
Is data access in such a project purely from in-memory sources?

yes.

I suspect most people shun it because database access- especially if the DB itself is over the network on a different machine- already slow enough that ZGC / zero allocation won't be noticed.

Database access, if you're talking network latency query/transaction processing time, is essentially irrespective of the language being used, so that's not a good reason to shun Java as a language/rutime anyway.

zdragnar
Oh, I'm not talking about shunning Java, but the zero-allocation style of coding while using Java.

If you have the extra network latency from external services, you need some pretty outrageous traffic for GC to become a problem, I would think.

nxobject
The elephant in the room is of course ZGC, which has been delivering great improvements in lowering the Stop-the-world GC pauses. I've seen it consistently deliver sub-millisecond pauses whereas other algorithms would usually do 40-60 msec.

As someone who's always been interested in gamedev, I genuinely wonder whether that would be good enough to implement cutting-edge combo modern acceleration structures/streaming systems (e.g. UE5's Nanite level-of-detail system.)

I have the ability to understand these modern systems abstractly, and I have the ability to write some high-intensity nearly stutter-free gamedev code that balances memory collection and allocation for predicable latency, but not both, at least without mistakes.

fidotron
As someone who's always been interested in gamedev, I genuinely wonder whether that would be good enough to implement cutting-edge combo modern acceleration structures/streaming systems (e.g. UE5's Nanite level-of-detail system.)

The GC would be the least of your problems.

Java is neat, but the memory model (on which the GC relies) and lack of operator overloading does mean that for games going for that level of performance would be incredibly tedious. You also have the warm up time, and the various hacks to get around that which exist.

Back when J2ME was a thing there was a mini industry of people cranking out games with no object allocation, everything in primitive arrays and so on. I knew of several studios with C and even C++ to Java translators because it was easier to write such code in a subset of those and automatically translate and optimize than it was to write the Java of the same thing by hand.

astrange
I'm honestly amazed people say this about Java, because the language almost couldn't be worse at giving you tools to use memory efficiently.

There's no value types (outside primitives) and everything is about pointer chasing. And surely if there was less pointer chasing it'd be easier to do the GC work at the same time.

vips7L
When people talk about GC performance they’re not talking about using memory efficiently. They’re talking about how fast the GC can allocate and how long it will stop the world when it needs to collect. In both of these areas you won’t find GCs better than the ones provided by HotSpot. Even with what you mention, pointer chasing and lack of structs, they still outperform other implementations.
tootie
The language has/had some rough edges that have been improved over the years, but the developer experience of using a strongly-typed, object-oriented language within a sturdy IDE like Idea is just second to none. The debugging process is so very straightforward. Java became synonymous with enterprisey bloated systems for good reason, but there is no pile of mud Java system that can't be stepped through cleanly with a debugger.

I'd also throw in what was possibly their greatest idea that sped adoption and that's javadoc. I'm not sure it was a 100% original idea, but having inline docs baked into the compiler and generating HTML documentation automatically was a real godsend for building libraries and making them usable very quickly. Strong typing also lined up nicely with making the documents hyper-linkable.

Java was really made to solve problems for large engineering teams moreso than a single developer at a keyboard.

topspin
javadoc

Indeed. Many languages have something similar to Javadoc, yet somehow I haven't encountered anything quite as good as Javadoc, and I can't explain why or exactly how it's better. I admit I haven't tried that hard either. But I suspect it's down to the nature of the language and how, with well designed libraries at least (and not all are, certainly,) there is a nice decomposition of modules, packages, classes/interfaces and methods that leads to everything somehow having a correct place, and the Javadoc just follows. The strong typing is another contributor, where 90% of the time you can just look and the signature and imply what is intended. Finally, the old-fashioned frames based HTML typically used with Javadoc is a great benefit.

Also, I've found I experience less reluctance to author Javadoc for some reason. Again, part of this is due to strong types, and much of the legwork being correctly generated in nearly every case.

Lombok, when used with moderation, is wonderful. Mockito is magic, of a good kind. Maven still gets it done for me; I've yet to care about any problems Gradle purports to solve, and I think that's down to not creating the problems that Gradle is designed to paper over in the first place.

Today, if I had my choice of one thing I'd like to see in Java that doesn't presently exist it's Python's "yield". Yes, there are several ways to achieve this in Java. I want the totally frictionless generators of Python in Java.

tootie
Indeed Gradle creates more problems than it solves. Maven is still the best build system in any language. Python finally has uv which is the first non-horrible build tool after so many years of being the most popular language.
datavirtue
This. It set the stage for modern enterprise software that we all take for granted now.
Terr_
I find these discussions have an interior split between the folks who are more concerned with getting the feature out now versus the folks who have had to keep a thousand ancient features running.
tootie
True, but it's also true that code spends 99% of it's lifetime in maintenance. That's the reason I am never impressed by tools that make it fast and easy to bootstrap.
lelanthran
Java performance isn't the fastest, that's ok, a close 3rd place behind C/CPP ain't bad.

When Java got popular, around 1999-2001, it was not a close third behind C (or C++).

At that time, on those machines, the gap between programs written in C and programs written in Java was about the same as the gap right now between programs written in Java and programs written in pure Python.

pjmlp
And yet many of us embraced Java, it became the chosen language to teach distributed systems in many Portuguese universities around 1998, because of the pain to write portable C or C++ code across UNIX clones.

A mix of K&R C, C89, C++ARM compilers catching up with WG21 work, POSIX flavours, and lovely autoconf scripts.

lelanthran
And yet many of us embraced Java,

That was my point - performance was never one of the primary considerations for enterprises. They had more important considerations.

pjmlp
Also as much as I complain about the lack of JIT tooling in CPython, many people forget that usually most people don't have any issues in polyglot codebases, it isn't a zero-sum game, and various forms of FFI and language bindings exist.

That is one of the things I have been doing across JVM/ART, CLR, V8 for decades now, moreso if we include Perl and Tcl into the mix, I seldom write full blown 100% C or C++ code, when I reach to them, is to write native libraries or implement language bindings.

int_19h
I don't think that's accurate. Java at the time you're describing was already JIT-compiled (HotSpot debuted in 1999), which made it drastically faster than any plain bytecode interpreter. OTOH Python was - and remains - notoriously slow because, despite being compiled to bytecode, said bytecode is extremely high level and many opcodes in it represent potential numerous dict lookups etc.
badc0ffee
Java performance isn't the fastest, that's ok, a close 3rd place behind C/CPP ain't bad. And you're still ahead of Go, and 10x or more ahead of Python and Ruby.

Fastest at what, exactly?

briankelly
Having a hard time finding it now, but someone put together a benchmark with two categories - naive and optimized - comparing implementations across languages with a workload vaguely resembling a real-world business application server with a mix of long and short lived objects. Java was at the top of the naive benchmark by a landslide and behind C and C++ (edit: and probably Rust) for the optimized ranking, but with a gap before the rest of the field.

With the JVM you basically outsource all the work you need to do in C/C++ to optimize memory management and a typical developer is going to have a hell of a time beating it for non-trivial, heterogenous workloads. The main disadvantage (at least as I understand) is the memory overhead that Java objects incur which prevent it from being fully optimized the way you can with C/C++.

lycopodiopsida
I think it was this blog: https://renato.athaydes.com/all-posts They also tested common lisp!
igouy
Which post?

Some of those posts "404 The page you have entered does not exist"

igouy
Having a hard time finding it now

So — Fastest at what, exactly? — is unanswered.

jonhohle
I’m slightly surprised there isn’t more KVM/Virtualized bare metal JVM environments. While I haven’t used it in a while, the decade+ I spent running Javan’s in production basically have the entire system over to the JVM (with some overhead for some small non-JVM background daemons). Most things were built not to use POSIX standards, but Java equivalents. Occasionally direct file system access for writes was necessary (logging being a big exception).

So giving the entire system to the JVM, performing some warmup prior to a service considering itself “healthy”, and the JVM was reasonably fast. It devoured memory and you couldn’t really do anything else with the host, but you got the Java ecosystem, for better or worse).

There was a lot of good tooling that is missing from other platforms, but also a ton of overhead that I am happy to not have to deal with at the moment.

dragandj
Throw in Clojure into the mix, and you get superpowers!
exabrial
I'm still trying to mentally grok the Clojure model and syntax hah. On my todo list. Clojure users seem to love it though. Do you have a tutorial that could sell it to me?
Zambyte
For syntax, maybe this general Lisp advice will help: consider a normal function call, like f(a, b). To make this into a Lisp function call, drop the unnecessary comma (whitespace is enough to separate tokens) like f(a b), and then move the function name inside the parentheses, like (f a b). Applying operators that are considered "primitive" in other languages are syntactically treated the same as functions. So imagine an add function like add(a, b), but instead of being named 'add', it's just named '+', like +(a, b). Applying the same transformation as before, this turns into (+ a b).

Using the function application syntax for primitives like + is nice because you get the same flexibility of normal functions, like variable argument length: (+ a b c).

Clojure is a little bit less uniform than other Lispy languages in that it has special brackets for lists (square brackets) and for maps (curly brackets), but that's pretty much it.

fuzztester
it also has the threading operator or macro.

i am not a clojure or lisp expert, just saying.

shawn_w
Clojure style threading macros are readily available for common lisp and scheme. Probably emacs lisp too.
fuzztester
interesting, thanks.
dragandj
Many Clojure tutorials are free! It's difficult to say without knowing nothing about your preference and experience. Everyone's welcome to join Clojure Slack community (for example) which has several tens of thousands of members and dedicated beginners channel. I'm sure if you asked there, you'd get tons of recommendations tailored to you. https://clojurians.slack.com/

(BTW Clojure, as a Lisp dialect, has almost no syntax. You can learn THAT in 5 minutes. The challenge is in training your programming mind to think in totally new concepts)

mark_l_watson
My Clojure AI book won't teach you the language, but afterward you read through a tutorial my book contains interesting examples; read it online https://leanpub.com/clojureai/read
dan_fornika
"Clojure for the Brave and True" is free online: https://www.braveclojure.com/clojure-for-the-brave-and-true/
wry_discontent
Start doing any year of Advent of Code with Clojure and you'll get it.

They're really amenable to the REPL.

jbellis
more like 100x faster than Python/Ruby

and that's before you throw in real multithreading

igouy
jbellis
iirc these benchmarks have such short runtimes that they are not useful for assessing real-world java jit performance
igouy
Is that a True Scotsman exclusion?

iirc

    49.88—55.68 secs wall clock
    7.66
    5.51
    27.85—27.91
    83.79—87.16 
    10.94—11.09
How long a runtime would be required exactly, on what class-of hardware, to pass the True Scotsman?

Please provide alternative benchmarks that you accept.

timbit42
I have heard around 50x, which is about the same as between assembly and BASIC on 8-bit systems.
igouy
Thaxll
Java is not ahead of Go, they're on part but often Go is faster while using 2-10x less memory. Value type makes optimization much easier in Go.

The fact that you specifically mention Go explains a lot. btw c# is faster than Java, so not third place, it's more a 5th~

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

999900000999
Doing what?

Benchmarks aren’t all that useful since usually the bottleneck is File IO, external api calls, db calls, user latency or a combo of the 4.

Go’s main advantage in this matchup would be conciseness.

Go code looks so clean and nice, Java doesn’t.

I personally don’t care for Java, but I have bills so it’s always in my back pocket. Things happen , sometimes you need to write Java to eat.

Fred, you really should just take the job.

Martha you don’t understand, it’s Java with an Oracle DB.

Fred, I know it’s bad, I know you still have nightmares about the 4 types of string in Java 8, but it’s not just us now.

With a tear in his eye , fear in his heart.

Martha, if I must… I’ll open Eclipse once more.
noisy_boy
I personally don’t care for Java, but I have bills so it’s always in my back pocket. Things happen , sometimes you need to write Java to eat.

I write Java to pay bills and my eyes and fingers thank me everyday for sparing them from a sea of if err != nil. I won't even go(!) into the iota stupidly compared to Java's enums.

999900000999
I want to like Go.

I built a small phone app with it. The best way to describe it is incomplete. I think the philosophy is to make things more minimal?

A lot of frameworks don’t exactly do everything they need to.

I’ll still pick it over Rust, which seems to like punishing the developer.

noisy_boy
I wrote an application in Go about couple of years ago that is still running in production without much maintenance. The language isn't bad as such + the single binaries are nice. But until they reduce the error handling noise (which I suspect they never will), I won't choose it voluntarily to write code. Rust is actually nice if one can accept cloning as a workaround. The error handling via ? is awesome in rust.
vips7L
Go code is far from concise. Java is more expressive than Go in almost every way.
KronisLV
I really like the JetBrains IDEs, both for Java and .NET, it feels way more pleasant to write code and refactor it than just in something like Visual Studio Code (which still feels better for utility scripts). They have pretty good run profiles that you can put in your repo, pretty good debugger, plenty of suggestions/inspections and customizability.

Java, .NET and languages like that also lend themselves pretty well to tools (and even LLMs) understanding what's going on, their runtimes are pretty good and platform differences don't give you too many issues from what I've seen. Though when it comes to the frameworks or libraries you might use (e.g. how often you will see the likes of Spring Boot in enterprise projects) will definitely leave some performance on the table[1] and have plenty of awkward and confusing situations along the way[2], especially if you're unlucky enough to have to work on codebases that have been around for over a decade. Old Java projects really suck sometimes, though maybe that applies to many of the old projects, regardless of tech.

Overall, I quite like them and am pretty productive, plus I unironically think that using Maven is pleasant enough (even adding custom repos isn't too convoluted[3]) and the modern approach of self contained .jar files that can just be run with a JDK install instead of separately having to manage Tomcat or GlassFish (or TomEE or Payara nowadays, I guess) is a step in the right direction!

Though while I do like packages such as Apache Commons and they're very useful, I also very much enjoy using something like Go more recently, it's easier to get started making simple web apps with it, less ceremony and overhead, more just getting to writing code.

[1] https://www.techempower.com/benchmarks/#section=data-r23&l=z...

[2] https://blog.kronis.dev/blog/it-works-on-my-docker (a short rant of mine, but honestly I very much prefer when you have configuration done explicitly in the code, not some layered abstractions with cryptic failure modes; Dropwizard is way nicer in that regard than Spring Boot)

[3] https://maven.apache.org/guides/mini/guide-multiple-reposito... and https://maven.apache.org/guides/mini/guide-mirror-settings.h...

javier2
Java syntax isn't perfect, but it is consistent, and predictable

This is something I greatly value with the recent changes to Java. They found a great way to include sealed classes, switch expression, project Loom, records that feels at home in the existing Java syntax.

The tooling with heap dump analyzers, thread dump analyzers, GC analyzers is also top notch.

aardvark179
I think Gavin Bierman is an unsung hero as far as steering the Java language is concerned. I had the privilege to sit next to him in the office when I was working on TruffleRuby, and our conversations on language design were always elucidating, and his ability to gently steer others away from pitfalls was something I wish I could do as well.

Hearing the work he and others did to gradually introduce pattern matching without painting themselves into a corner was fascinating and inspiring.

nxobject
Third best consistently used over 3 decades adds up to a great, great deal. Although, to be fair, a great deal has been invested in cutting edge GCs for the JVM – some fresh out of research.
emmelaich
As an SRE, I appreciate the JVM. Out of memory is now the developers problem not mine / the machine's.

Only have to deal with gigalines of log4j excreta filling up disks.

thomashabets2
I know many SREs who basically became full time JVM herders. That thing is a nightmare.

But if your organization doesn't assign that work to you, then sure, it's not your problem.

igouy
Java performance isn't the fastest, that's ok, a close 3rd place behind C/CPP ain't bad. And you're still ahead of Go, and 10x or more ahead of Python and Ruby.

Of course, rank depends on what we include or exclude from the rankings, for example:

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

:versus:

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

interleave
I miss writing Java 1.4 with Eclipse and svn. Even though I am also super-happy with Ruby and Swift today, I know that control-space flow. Good times!

Edit: 1.4, not 1.7

pjmlp
And, alongside C# for historical reasons, the closest we got in mainstream to the whole Xerox PARC ideals of what a developer workstation is supposed to be like.
neonsunset
a close 3rd place behind C/CPP

Not anymore, the competition is doing much better these days.

nelup20
I personally appreciate Java (and the JVM) much more after having tried other languages/ecosystems that people kept saying were so much better than Java. Instead, I just felt like it was a "the grass is greener" every time. The only other language that I felt was an actual massive improvement is Rust (which so far has been a joy to work with).

It's a shame imo that it's not seen as a "cool" option for startups, because at this point, the productivity gap compared to other languages is small, if nonexistent.

kllrnohj
Personally I think C# is miles ahead of Java and in meaningful ways (like a drastically better implementation of generics, not to mention value types have existed for eons at this point and an FFI system that doesn't hate you for using it)

But nobody seems to talk about or care about C# except for Unity. Microsoft really missed the boat on getting mindshare for it back in the day.

breadwinner
One area where C# really messed up is exception handling.

See https://mckoder.medium.com/the-achilles-heel-of-c-why-its-ex...

neonsunset
IIRC all previous conversations about checked exceptions here ended up with the swift conclusion that they are heavily discouraged throughout Java code.
breadwinner
they are heavily discouraged throughout Java code

That's so ignorant. Read the article please.

neonsunset
Let's revisit past conversations:

- https://news.ycombinator.com/item?id=43226624

- https://news.ycombinator.com/item?id=43584056

- https://news.ycombinator.com/item?id=36736326

And more. I'm not sure what you found in (checked) exceptions. If you'd like explicit error handling, we have holy grail in the form of Rust which beautifully solves it with implicit returns, error type conversions and disambiguation between error and panic model. I'd prefer to use that one as it actually reduces boilerplate and improves correctness, the opposite to the outcome of using checked exceptions.

breadwinner
I'm not sure what you found in (checked) exceptions.

I could copy/paste the entire article here... but it would be easier if you could take a gander: https://mckoder.medium.com/the-achilles-heel-of-c-why-its-ex...

Summary:

Crashy code: You have no compiler-enforced way to know what exceptions might be thrown from a method or library.

More crashy code: If a method starts throwing a new exception, you might not realize you need to update your error handling.

Dead code: If a method stops throwing an exception, old catch blocks may linger, becoming dead code.

Kwpolska
None of those arguments are convincing. In many cases, you can't handle errors more reasonably than just crashing or telling the user something went wrong. Java has RuntimeExceptions, which do not have to be declared in the function signature. Division by zero, or trying to index an array out of bounds, and the dreaded NullPointerException, are some examples of RuntimeExceptions.
breadwinner
What about the ones you can recover from? You don't want to crash the entire application every time there's an exception!
Kwpolska
You usually wouldn’t crash the entire application, the request that causes the issue will return a 500 error. (Or equivalents for non-web environments.)
breadwinner
Some exceptions are not recoverable and may cause 500 error. Others such as FileNotFound are recoverable, for example by reading the file from an alternate location.
mrkeen
You have no compiler-enforced way to know what exceptions might be thrown from a method or library.

Always assume exceptions will be thrown from a method or library.

breadwinner
Which ones? That's the issue.
bigstrat2003
I'd prefer to use that one as it actually reduces boilerplate and improves correctness, the opposite to the outcome of using checked exceptions.

Reducing boilerplate is not a valuable goal in and of itself. The question is, does the boilerplate buy you something? I think that with checked exceptions it does. Having an explicit type signature for what errors a function can raise improves correctness a great deal because the compiler can enforce the contracts of those functions.

I agree that the Rust approach is good too, though I don't agree it has any strong advantages over the way Java does things. Both approaches are equally respectable in my view.

jayd16
Java streams and a lot of other APIs are extremely ugly because of checked exceptions. Conversely, LINQ and delegates and a lot of other syntax is far cleaner in C#.

Your linked blog is pretty wild. Only throw RuntimeExceptions to crash? Why not just Exit if that's the proper thing to do?

If you treat all C# exceptions as RuntimeExceptions, then it satisfies the blog anyhow.

breadwinner
Side effects are not allowed in functional style programming. Exceptions are side effects, it doesn't matter whether they are checked or unchecked exceptions.

https://jessewarden.com/2021/07/why-functional-programmers-a...

While composing methods in stream style is convenient, methods that can throw exceptions warrant more careful coding, so convenience should not always be the priority.

int_19h
Exceptions are not side effects since no state mutation occurs.

If you really want to see everything through the FP lens, exceptions are exactly like Result<T, E> with implicit do-notation.

vips7L
Checked exceptions could still work across lambdas. Scala is doing research there: https://docs.scala-lang.org/scala3/reference/experimental/ca...
int_19h
One of the original lambda proposals for Java - the one from Neal Gafter - also had checked exceptions.

The problem is that you then need a way to capture exception specifications as generic type parameters to properly propagate contracts, which complicates the type system quite a bit. Which is why Java ultimately went with the much simpler proposal that didn't even try to tackle this.

vips7L
Yes I'm well aware, but that is uniquely a Java problem. With a sufficiently strong type system, like the one in Scala, you can easily make checked exceptions work across higher order functions.
breadwinner
Why not just Exit if that's the proper thing to do?

Because you won't get a stack trace.

bigstrat2003
I don't know that I'd say "messed up", but I do wish C# had checked exceptions. I strongly believe that they are superior to non-checked exceptions, basically static type signatures but for error handling. It's a real pity that everything after Java seems to have abandoned the idea.
kllrnohj
Java itself has basically abandoned the idea, or at least the ecosystem at large has. Checked exceptions are a decent idea but Java's implementation sucks. It needs to be a lot more automatic or something
breadwinner
Java itself has basically abandoned the idea

Some Java developers may have, due mostly to misinformation from the .NET camp.

easton
They intentionally chose to not have checked exceptions though, and people have different opinions on it. They believed that people would just catch Exception most of the time anyway instead of selecting on a very specific type (which is often how it works, in web apps anyway.)

https://www.artima.com/articles/the-trouble-with-checked-exc...

breadwinner
They believed that people would just catch Exception most of the time anyway

Their belief was wrong. Microsoft now recommends against catching Exception.

The article you linked to is addressed at the bottom of this article: https://mckoder.medium.com/the-achilles-heel-of-c-why-its-ex...

echelon
That's because the Microsoft of 2000 - 2014, the Ballmer era, was Microsoft-first. It didn't care about other platforms, it didn't care about the web, and it didn't care about open source. C# could be great, but it existed in a bubble.

Java kept growing and wound up everywhere. It played nice with Linux. Enterprise Mac developers didn't have trouble writing it with IntelliJ. It spread faster because it was open.

Satya Nadella fixed a lot of Microsoft's ills, but it was too late for C# to rise to prominence. It's now the Github / TypeScript / AI era, and Satya is killing it.

The one good thing to say about Ballmer is that he kicked off Azure. Microsoft grew from strength to strength after that.

fuzztester
Satya Nadella fixed a lot of Microsoft's ills,

which ones?

echelon
So many.

Microsoft isn't thought of as evil anymore, but is open source and Linux friendly. GitHub, VScode, Typescript. Azure is booming, ...

But the big one: stock price.

int_19h
Funny you should mention open source and VSCode.

VSCode itself, for all the promotional materials about how it's open source, is officially "a distribution of the Code - OSS repository with Microsoft-specific customizations released under a traditional Microsoft product license".

But wait, you might say, it's just like Chrome vs Chromium - so long as we have the OSS edition, it's all good! But, unless you're writing JS or TS, you need extensions to do anything useful. Python is an extension. So is C#, and C++. And all of these are partially closed source - e.g. code completion for all three, or debugging for both C# and C++.

Worse yet, the licenses for those closed source parts specifically prohibit their installation and use in anything other than the official closed source VSCode distro. And this isn't just verbiage - there are actual runtime checks in all these products that block attempts to use them in VSCodium, Cursor etc.

The same goes for the official VSCode extension gallery / marketplace - you can't legally use it from anything other than the official VSCode. Enforcing that is trickier, but even here Microsoft managed to find a way to frustrate its users: it used to be possible to download a .vsix from the Marketplace, but that feature has been removed recently, precisely because people were using that in conjunction with Cursor etc.

Much open source, indeed.

Squeeeez
Microsoft isn't thought of as evil anymore

Maybe you don't think of it like that, but please remember that, especially with some decisions made in the past months, more and more people are turning away from everything Microsoft.

bsaul
Problem with C# isn't the language, it's the enterprise ecosystem. You always feel like you're going to have to pay at some point down the road for using the tech.
hu3
I don't see Java being any better in this regard.

Microsoft has been historically much less aggressive with lawyers compared to Oracle.

frontfor
That might be true for other Oracle products like the DB, but has that been true for Java and openjdk?
homebrewer
Sure. Here's just one example I was able to quickly find in the browser history:

https://www.theregister.com/2025/05/09/users_advised_to_revi...

You can easily just not use the Oracle JDK, though, unless you're running commercial software which requires running on the Oracle runtime to get technical support.

As others have said, the problem is not the runtime, but libraries: many major .NET libraries have been going fully commercial, you can't really trust the ecosystem anymore.

antod
The poster was talking about the ecosystem not the core platform. The wider Java ecosystem was heavily dominated by many Apache (and other) open source libraries vs commercial products for the C# ecosystem.
neonsunset
Most of the features that require Apache or community packages in Java ship out of box in .NET (or via extension packages).

They also tend to be of higher quality and provide better performance.

cyberax
Java has a strong history of OpenSource, and a great set of libraries. It also pioneered the managed dependency system early (Maven), so these libraries have been centrally available for two decades.

Moreover, a lot of these libraries are well-supported to this day. For example, Hibernate (the best ORM in business) is 28 years old, and has just released a new version. I recently consulted my former client (from 15 years ago), and I still recognized most parts of the stack that I set up way back then.

wslh
I think OP means that .NET has strong connections with Microsoft technologies where it is a natural decision to use Azure instead of AWS.
cgh
Every large company I’ve ever worked at had a strict “no Microsoft on the server” policy and for better or worse, C# is closely identified with Microsoft.
runjake
IOW Linux on the server?
nextos
C# had the chance to learn from Java. Java was a bit rushed. Gosling said he was not given enough time to add closures. Even without generics, Java would have been quite elegant and much less verbose. The alternative, anonymous inner classes, were quite clunky.

Nevertheless, as a platform, the JVM and JDK were fantastic and miles ahead most alternatives during the late 1990s and 2000s. The only platform for large development that offered some compelling advantages was Erlang, with BEAM and OTP.

hocuspocus
Java could have easily caught up with C# in the early 2000s. In 2001 Pizza (Scala's ancestor) showcased generics, higher-order functions, ADTs and pattern matching. Interestingly enough only generics made it to Java in a reasonable timeframe, the rest came only much later.

Aside from early versions being rushed, I feel that Java's success and adoption were the bigger issue. While Microsoft could iterate quickly and break backwards compatibility with major versions of C# and the .NET runtime, Java was deliberately moving at a much slower pace.

int_19h
In fact, Java 1.5 got generics in 2004, one year before C# 2.0 added them in 2005. OTOH C# 2.0 had anonymous delegates, although syntactically they were still very verbose (no type inference for arguments) and thus only marginally better than Java's anonymous classes.

It was really from 2007 on (.NET 3.5 / C# 3.0) that C# started to get major features at an ever increasing pace while Java significantly stagnated for quite a long time.

hocuspocus
Thanks, my recollection of C# evolution was blurry, I stand corrected.

So really, Sun and Oracle could have definitely moved faster around Java 6 and 7, the Java 8 release took a long time given the feature set.

I feel that records could have come quicker, their implementation isn't exactly ground breaking. Avoiding the async/await route was a smart call though, and Loom could probably not have happened much earlier.

Valhalla is another can of worms entirely

wokkel
It barely works on non MS platforms,has had many slightly incompatible versions so it's a non starter for many projects where I run into that might benefit from c#. I spoke to a manager recently who had invested in silverlight in the past. Based on that alone it was a no MS policy for his development teams.
neonsunset
Quite a few languages "loved" by "Linux communities" tend to have rather rudimentary integration with Linux kernel's facilities or worse packaging story.

For example, Go does not understand cgroups limits and needs an external package to solve this. .NET can read and accommodate those natively. It also ships with excellent epoll-based socket engine implementation. It's on par with Go (although I'm not sure which one is better, but .NET performs really well on high-throughput workloads).

runjake
AFIACT, either most or at least a significant percentage of dotnet code runs on Linux, depending on the industry.
tester756
It barely works on non MS platforms

What a bullshit

I've been running C# on Linux on production web apps backends since 2018 and had no issues

astrange
But nobody seems to talk about or care about C# except for Unity. Microsoft really missed the boat on getting mindshare for it back in the day.

There was this guy Miguel de Icaza. From when I followed the open source ecosystem at the time, it seemed to be his personal mission to promote independent clones of a bunch of Microsoft technologies like C# on his own time even though they didn't ask him to do it.

I don't think I ever understood why someone would do this. It's like in the 2000s where people seemed to think you could solve all technical problems by inventing new kinds of XML.

bitwize
The founding document of GNOME was written by de Icaza. It was called "Let's Make Unix Not Suck", and his proposal for not sucking was basically to import much of the design of Windows and specifically COM into Linux as open source.

https://web.archive.org/web/20000815075927/http://www.helixc...

Miguel de Icaza has been stanning for Microsoft technologies, literally since the nineties.

dagw
nobody seems to talk about or care about C# except for Unity

C# is extremely popular in all kinds of 'boring' industries. Having worked in areas like logistics and civil engineering, C# is everywhere.

throw1235435
Depends where you work. I've seen a lot of Java and .NET jobs around where I am. Having both jobs I find it easier to get performant code in .NET than Java (reified generics, value types, more primitives/less boxing in general, and other constructs not found in Java)
jayd16
Its actually quietly very popular in very boring contexts outside of Silicon Valley. Its also slowly entering new areas now that Linux builds are rock solid.

MS does have an uphill PR battle though.

watwut
Definitely not. All the stuff I was used to get for free and advice I that was one google search away ... just dont exist in dotnet. Or is expensive. But most of the time, there is weaker library not doing nearly enough and that is all that exists.
astura
C# isn't popular in startups for the same reason Java isn't, it's "boring."

It's an extremely common language in "boring" companies doing "boring" (but profitable) work.

bsaul
Funny. I've been trying rust for the past 2 months fulltime, and i'm really wondering how you can call it a "joy to work with" when compared to java, at least for server development.

Rust feels like walking on a minefield, praying to never meet any lifetime problem that's going to ruin your afternoon productivity ( recently lost an afternoon on something that could very well be a known compiler bug, but on a method with such a horrible signature that i never can be sure. in the end i recoded the thing with macros instead).

The feeling of typesafety is satisfying , i agree. But calling the overall experience a "joy" ?

mynameisash
I've been trying rust for the past 2 months fulltime,

recently lost an afternoon on something that could very well be a known compiler bug

With respect, at two months, you're still in the throes of the learning curve, and it seems highly unlikely you've found a compiler bug. Most folks (myself included) struggled for a few months before we hit the 'joyful' part of Rust.

bsaul
i didn't "find" it. As i said, it's a well known one : https://github.com/rust-lang/rust/issues/110338

Simply using axum with code using multiple layers of async was enough.

But then again, it looked like this bug (the error message is the same), however at this point i'm really unsure if it's exactly the same. The error message and the method signature was so atrocious that i just gave up and found a simpler design using macros that dodged the bullet.

heavyset_go
IME, new users do weird things that can expose bugs no one ran into because they wouldn't think to do things the weird way.
bsaul
I hope the same, and TBH it's the only reason i'm keeping up developing that backend in rust. I hope that in the end, it's going to improve my style.

Go felt the same way (but with a much lower order of magnitude) : you feel like bumping into language limitations, but once you learn to do it "simply" in go, your style will have changed into something much more elegant.

As for the bug in question, it has been quite "popular" for about 5 years now, and is actively tracked : https://github.com/rust-lang/rust/issues/110338. Nothing really weird. Just async hitting the limits of the current rust design.

johnisgood
Okay, but I have hit the joyful part of some other languages long before a few months. What gives?
asa400
Rust is genuinely novel, so for most of us its going to be less familiar, so it will take longer to learn. It's not like learning Python if you already know Ruby, for example. The upside is that it offers some pretty great guarantees you can't (yet) find elsewhere. If you want those guarantees it will be worth it, if those guarantees don't matter to you, it may feel like a slog.
johnisgood
What guarantees are you speaking of exactly?
asa400
The banner one is memory safety without garbage collection. This enables is a terrific degree of library composition. Unlike C/C++, you can generally expect that libraries you pull in will also be memory safe.

The other one is thread safety, due to the compiler-enforced ownership semantics that prevent threads from accessing shared data unless they do so in a well-defined way.

vips7L
With respect, at two months, you're still in the throes of the learning curve,

It shouldn’t take 2 months of full time programming to beat the learning curve.

treyd
You eventually learn you leverage lifetimes. You just need to get over that point in the learning curve. I very rarely run into those types of issues, and it's very freeing knowing that I can write libraries that are so hard to misuse because you can leverage the type system.

And macros are a part of that!

rwmj
Why do I need to? Why can't I let the garbage collector deal with it?

Rust's macros on the other hand are excellent, and more languages should have expressive macros like that.

treyd
You need lifetimes in order to make the affine types ergonomic to use through borrowings and aliasing mechanics. You want the affine types to prove all kinds of things about resource management, beyond just freeing allocations, which we generally call RAII. You model file and network handles as RAII, mutex locks as RAII.

Other languages use constructs like context managers or try-with-resources to capture this, but these constructs are very limited and make it very hard or impossible for these resource types to be put into a container and passed between threads. In Rust this is trivial and actually just works.

Garbage collectors usually give much weaker guarantees about when objects are freed, so destructors (which are sometimes not even available, like in JS) might only be called much later. You can't rely on a GC to unlock a muted for you. But in Rust it happens when the guard is dropped, always, immediately after it's last needed.

bsaul
Since you're mentionning it : i was surprised to find no golang "context" equivalent in rust's axum. How do you manage cancelling a long-running operation triggered inside an http request handler when the connection closes ? is it via RAII ?
treyd
Yeah due to the design rule that "futures do nothing unless polled", it's enough to simply drop them and it cancels the whole tree of work. That doesn't necessarily cancel other tasks that were spawned that the future might have been waiting on. That's really easy to build if it's needed, since we do have RAII. This is part of why Rust's futures compose really well in ways that goroutines just do not and JS promises struggle with.
bsaul
Never thought of it like that. Super interesting, thanks.

Edit: isn't that the case for all "async" systems, in every language ?

bitwize
Why do I need to? Why can't I let the garbage collector deal with it?

Determinism.

With Rust lifetimes, you can statically prove when resources will be released. Garbage collectors provide no such guarantees. It has been shown that garbage-collected languages have a space-performance tradeoff: you need five times as much RAM to achieve the same performance, even with a "good" GC, as the same program with explicit memory management:

https://people.cs.umass.edu/~emery/pubs/gcvsmalloc.pdf

int_19h
That's a paper from 20 years ago. GCs have improved since then.
bsaul
i indeed got the feeling that rust style favors macros over complex function signatures.

I'm still unsure if it's a good thing in general, because as a general rule meta programming is always harder to debug. But for simple macros it seems like a nice trick.

asa400
I'm not discounting your experience, or saying you're wrong or anything like that. I've been writing Rust for a while, and for me, that feeling went away. Lifetime/ownership problems used to run me over but it almost never happens anymore. I think Rust has a rather severe "hump" that a lot of people run headlong into, but it does get better, I promise you. You start thinking in ownership/borrowing terms and it just fades into the background at some point. Rust is easily my most productive language now. Again, not discounting your experience at all, it can be rough starting out.
bsaul
i do feel much more comfortable with lifetimes than at the beginning. I get the general concept, and i barely have to explicitely set them (i did start by religiously reading the rust book, of course).

However, at the moment i still feel i'm using a huge amount of layers upon layer of complex type definitions in order to get anything done. Just using an object's reference across async calls in a safe manner leads to insane types and type constraints, which read like ancient egyptian scripture. And at every layer, i feel like changing anything could blow everything up with lifetimes.

The language has this very special feel of something both advanced and extremely raw and low-level at the same time. It's very unique.

charlotte-fyi
In my experience, beginners often make the mistake of assuming just because you can do things with references and lifetimes that you should. Unless you’ve done profiling, just start with the easy thing and clone an `Arc` (or whatever other data structure helps you avoid lifetime problems)!

Also, it’s worth saying, you probably don’t need async.

bsaul
oh, believe me, cloning and Arc-ing is something i realized very early that i was going to use. But that's the point: you still end up with things like : Arc<tokio::RwLock<dyn MyTrait>> for every single dependency.

Then you want to declare an async function that takes an async closure over that dependency. And you end up with a total garbage of a method signature.

As for async, the ecosystem for server-side is totally filled with async everywhere now. I don't think it's realistic to hope escaping those issues anyway in any real-world project. i thought i might as well learn to get comfortable with async.

debugnik
Not all lifetime problems are just a matter of learning. I've been picking up Rust every few years to catch up, and every single time I've eventually expressed a lifetime that either required unstable Rust at the time or hit a known lifetime bug.
worik
I've been trying rust for the past 2 months fulltime

Rust has a horrid learning curve

I've programmed for decades in many languages, and I felt the same as you

Persevere.

Surrender! to compile

Weather the ferocious storm

You will find, true bliss

bsaul
I am keeping up, but honestly i feel like rust dev is a bit like a trap : people like us love challenges and solving technical problems. So whenever we "triumph" over a rust tricky compilation issue, we feel intense gratification in solving it.

However, at some point you have to ask yourself why you're accepting to face all those challenges. Is it worth it ? When was the last time i faced a race condition when developping a backend ?

The reason i started with rust was for a very specific need on building a cross-platform library (including wasm), and that was a good justification, and i'm happy that i did. However now that i'm using it for the server as well and face the same kind of challenges, i seriously question whether this is a wise choice.

worik
Generally Rust is the wrong choice.

Generally garbage collectors are very worthwhile

But whe you need it, it is so much better than C or C++

sapiogram
My feelings exactly. Go was particularly disappointing, it promised everything but only felt like a sidegrade from Java. Screw it, a downgrade, until go errors get stack traces.
overfeed
The reason I prefer the Go ecosystem to Java is cultural, rather than technical. Sure, the JVM is very impressive and the language has been evolving, but the culture around Java seems to encourage needless complexity.

Of all the languages I've had to work with trying to get to know unfamiliar code-bases, it's the Go codebases I've been quickest to grok, and yielded the fewest surprises since as the code I'm looking for is almost always where I expect it to be.

whartung
The don't embrace that culture. Embrace a simpler culture. Strive for simplicity. Push for fewer dependencies.

Simple example, JAX-RS running on top of Java SE. I agree, JAX-RS is not what one might call "simple". It IS complex, or I should say, it CAN be complex. But Happy Path, staying in the middle of the road, it's pretty sweet for knocking out HTTP backed services. The Jersey reference implementation will do most anything you need (including stuff not "included" in raw JAX-RS). No need for a container, no need for a lot that stuff and all that hanger-on. The core runtime is pretty broad and powerful.

Consider my current project, it uses the built in Java HTTP server. Which works! It's fast, it's functional, it's free. (Yes, it's in a com.sun.net... package, but it's not going anywhere.) It's awkward to use. It's aggravatingly raw. It follows the tenet "why be difficult, when, with just a little effort, you can be impossible."

So, I wrote a simple "servlet-esque-ish" inspired layer for response and request handling, a better path based regex-y router, and a nicer query parser for queries and forms. 500 lines. Add on a JSON library and I can process JSON-y web request/response, easily. (I also wrote my own Multipart processor -- that was another 500 lines, boy that was fun, but most folks don't need that.)

A little bit of code and the built in server is MUCH easier to use. No tomcat, no deploys, zip. ...and no dependencies (save the JSON library).

Something all of these cool frameworks and such have shown me is what's really nice to have, but at the same time, just what isn't really necessary to get work done. I mean, CDI is really neat. Very cool. But, whoo boy. So I have a single singleton to handle application life cycle and global services. It works great with tests. I have a 50 line Event Bus. I have a 100 line "Workflow Engine". 150 line java.util.Logger wrapper (which is mostly, you know, wrapper). I wrote that way back whenever they introduced varargs to java (Java 5? 6?). The modern Java logging landscape is just...oh boy. I'm content with JUL -- I can make it work.

My current project is "magic free". I think @Overide in the single annotation anywhere in it. But it's comfortable to use, the cognitive load is quite load (outside of the actual application itself, which is NOT low -- sheesh). No swearing at frameworks. It's all my fault :).

Anyway, the point is that "simple Java" lurks in there. It needs a bit of uplifting, but not a lot.

password4321
You've made the project yours, nice! How many others work on it?

It's an uphill battle to convince my co-workers to do things my way.

wpollock
You've made your point, but note the built-in HTTPS server only supports TLS 1.2, so don't use that for production code. (For testing it's probably fine.)
whartung
TLS is supplied by the underlying JDK, which has been 1.3 for some time. How is HttpsServer not 1.3?
wpollock
Not sure, but the API docs say 1.2. Maybe the com.sun packages include their own implementation of TLS, separate from the TLS used in the rest of the JRE.
skydhash
I think kotlin is what Java should have been like. The same capabilities but with less cumbersome constraints.
ori_b
When I used Kotlin, it felt like Java, but with the antipatterns baked in as language features.
complexworld
Could you explain which antipatterns you're referring to?
ori_b
Leaning heavily into object orientation, including baking in things like companion objects, object expressions, etc. Encouraging utility classes that tack half-baked functionality onto existing types. Smart casts encouraging overly complex hierarchy.

While operator overloading and infix functions aren't a Java anti-pattern, I also think the language would be improved by their removal.

int_19h
Even if you sincerely believe that OOP is an anti-pattern, surely it was firmly "baked into the language" in Java already? Kotlin is fundamentally a better Java, not a rebuttal to Java.
Zambyte
It is all but impossible to use Kotlin without an IDE telling you everything, and for that I find the language interesting. And for comparison, I did in fact write Java without an IDE for an extended period of time.
LtWorf
True, but the culture around go isn't any better. In my experience go developers are former java developers so they have the same culture of thinking it's ok to ignore how a unix system works. So you will have awful logging, daemons that never report they're ready, badly handmade command line parsing and so on.
arccy
funny. java is known for its stacktraces where you need 3 vertical monitors stacked together to see the whole thing and it still doesn't tell you anything useful about why the app crashed.
frontfor
Compared to Go where I always have to remember to print the stack trace in every goroutine’s panic handler or use a custom error type that includes the stack trace or I get nothing? And I have to do this very basic thing for every service I spin up? This might not matter for pet projects or CLI applications, but it matters a lot in large scale mission critical servers.
lenkite
Tip of the Day: You can wrap errors using "fmt.Errorf" in Go - this gives you a nice chain of error messages which is a pseudo stack trace. Another tip is to define and leverage sentinel errors when wrapping errors so you can test using "errors.Is" higher up when doing error handling in the call-hierarchy - like when mapping to http errors or exit codes.

Using "fmt.Errorf" is lean and painless compared to defining custom errors.

homebrewer
And be very careful in constructing your error messages so that grepping the error string does not return you 50 matches. It's not the same as getting the error message + file name + line number.

This is the whole story of Go, they pick something established and reimplement a heavily cut down version of it for "reasons", then slowly catch up to competition over the next decade or so.

dontlaugh
It’s still not stack traces for every error, which is the default in every other language with stack unwinding.

In practice you have to use a combination of error wrapping and custom stack trace errors for your production logs to be useful on failure. The stdlib errors really should have stack traces.

marginalia_nu
I think that's a bit unfair. Generally the stacktraces tell you exactly what and where the problem is. Generally shouldn't be more than a dozen lines or so.

The main area they get excessively lengthy is in certain frameworks and testing tools that can add like 100 lines to the trace.

jjav
stacktraces where you need 3 vertical monitors stacked together

If you wrote code with such deep stacktraces, it's all on you.

There's a performance cost to all that excessive stack depth too, often.

int_19h
This is unfortunately common across most ecosystems today. Such lengthy stack traces are routine in JS, and fairly common in C++.
hu3
as someone who had to deal with Java stack traces the entire week, I feel attacked.

God bless Gemini 2.5 Pro which ate all the traces for breakfast.

deepsun
My opinion on that is the projects scale. Typically people came from a 10+ year Java project of 100+ engineers, to a greenfield advanced hello-world -- of course it's going to feel better and more productive.

Also, as open-source folks say, "rewrite is always better". It also serves as a good security review. But companies typically don't have resources to do complete rewrites every so often, I saw it only in Google.

sabellito
I've worked in 3 of the biggest rails codebases in the world (Shopify being the last) and I can say from experience that rails legacy monoliths are infinitely worse to work with than some awful, but harmless, sea of struts XML legacy.
stevoski
I find this really interesting, and meets my (limited) Rails experience and (extensive) Java experience:

I found it hard taking over an existing Rails project - it felt frail to me, that any small change might have unexpected consequences.

Whereas when I've taken over Java projects - or come in late to an existing team - I felt quite confident getting started, even if it is a bit of a mess.

sabellito
It's mostly because of the compiler, but ruby also makes it extremely easy to shoot oneself in the foot with magic.
watwut
Same here. I started to really like java after working with js/ts on small to medium project. I started to love java after working in on medium to little big project.
bdangubic
same! mid-way through my almost 3 decade career I got bored and thought lets try some non-JVM projects, for 2 years I took projects using other languages etc… worse two years of my career :)
toprerules
I admire Java as a success story, but I still have a deeply ingrained aversion to it for many reasons. I will admit that many of the reasons are due to Java's legacy as the language of bloated corporations, and its creation of overly verbose, magic fueled frameworks and poorly written code. Java as a language goes hand in hand with the idea that code is coal to be shoveled into the furnace, and we should all throw our aspirations away and embrace mediocrity.

My other issues with the JVM is how much of a black box it is from a platform perspective, which makes debugging a PITA with standard ops tools like strace, gdb, etc. The JVM's over allocation of memory robs the kernel of real insight as to how the workload is actually performing. When you use the JVM, you are completely locked in and god help you if there isn't a JVM expert to debug your thing and unravel how it translates to a platform implementation.

Then of course there's the weird licensing, it's association with Oracle, managing JDK versions, it's lack of it factor in 2025, and a huge boatload of legacy holding it back (which is not unique to Java).

I have successfully navigated my career with minimal exposure to Java, and nowadays there's a glut of highly performant languages with GC that support minimal runtimes, static compilation, and just look like regular binaries such that the problems solved by something like the Java or Python VMs just aren't as relevant anymore - they just add operational complexity.

To reiterate, I admire JG just like any tech person should. Java's success is clear and apparent, but I'm glad I don't have to use it.

exabrial
My other issues with the JVM is how much of a black box it is from a platform perspective, which makes debugging a PITA

Java has one the greatest debugging capabilities ever. dynamic breakpoints, conditional breakpoints, hell you can ever restart a stack frame after hot deploying code without a restart. You can overwrite any variable in memory, set uncaught exception breakpoints, and even have the JVM wait for a debugger to connect before starting. There is no equivalent in any other language that does _all_ of these things. And to top this off, there is 0 equivalent to Idea or Eclipse for any other language.

For runtime dynamics, JMX/JConsole is good enough for daily use, Java Flight Recorder gives you deep insight, or in a system you don't have direct access to. Hell even running jstack on a JVM is a good debug tool. If those don't do the trick, there's plain old HPROF (similar to other languages) and Eclipse Memory Analyzer.

Then of course there's the weird licensing,

The JVM is open source. There are no licensing issues. OpenJDK can be freely downloaded and run in production without restrictions on any use. If you really want to buy a JVM from Oracle... well thats your prerogative.

it's lack of it factor in 2025,

sdkman

a huge boatload of legacy holding it back

what legacy code?

int_19h
dynamic breakpoints, conditional breakpoints, hell you can ever restart a stack frame after hot deploying code without a restart. You can overwrite any variable in memory, set uncaught exception breakpoints, and even have the JVM wait for a debugger to connect before starting. There is no equivalent in any other language that does _all_ of these things

.NET + C# can do all of these things.

exabrial
I was referring to the entire list above, that's what I was referring to
marginalia_nu
what legacy code?

The Java API has its fair deal of baggage due to its extreme backward compatibility. Boolean.getBoolean[1] is one of the more accessible examples of a bad API that exists only because of legacy reasons, but there quite a number of them.

[1] https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean....

exabrial
Ow.
throwaway7783
In my 20+ years using java, not once have I used strace or gdb. Java itself has fantastic debugger support, and IDEs have built in step through capabilities.

Mentioning Java and Python in the same way in the context of performance is really odd. Python is nowhere near the JVM when it comes to performance

toprerules
It sounds like you've only ever written code without dealing with it in production. You can't always plug your code into an IDE when your debugging someone else's JVM app on a remote server.
lenkite
Please - you can definitely do this in Java. Its been a standard basic feature of Java tooling for 25 years now. (Its the equivalent of saying that Rust doesn't have a package manager).

I strongly urge reading some elementary tutorials to educate yourself.

See https://www.baeldung.com/java-application-remote-debugging for CLI based remote debugging

But most people use IDE's.

See https://www.jetbrains.com/help/idea/debugging-your-first-jav...

and https://www.jetbrains.com/help/idea/tutorial-remote-debug.ht...

Java's debugging experience is better than any language out there - with the possible exception of Common LISP. I always cry when I need to debug a project written in another language after so much comfort using Java.

throwaway7783
Eh, okay. Sounds like you don't know how to do this in production.
vips7L
Except you can. Remote debugging is a huge feature.
jjav
My other issues with the JVM is how much of a black box it is from a platform perspective, which makes debugging a PITA

You state how you don't really use java, but the above confirms it.

Java debugging and diagnostic tooling is second to none.

toprerules
That's a really narrow view of the world, and I think another Javaism to think that Java is the entire world. Today's multi-service deployments run tens if not hundreds of auxiliary processes not using Java. They use network overlays that change how processes interact with the network core. A person who is debugging a knock on effect issues has to be able to look through many different layers of processes, many of which are written in C, C++, Go, etc. Having to learn an entire toolset to debug Python or Java is a huge burden and it makes introspection extremely difficult. Java essentially wants to be the entire platform, which isn't how the world works anymore.
jjav
When you need to debug across the entire system and into the kernel, I'd use dtrace which has had java stack frame support since... I don't remember anymore, but closing in on 20 years.
toprerules
No one uses dtrace anymore. bpftrace is integrated into the kernel and can extract btf type information embedded into the kernel binary.
bcantrill
Your (absurdly) broad claim is false -- and it's very easily disproven.[0]

[0] https://ahl.dtrace.org/dtrace-conf-2024/

vips7L
Don't you think a narrow view of the world is this idea that you should be able to use one tool to debug everything? It seems like you want GDB (and the unix's where it runs) to be the entire platform.
the_overseer
IT factor! Am I on a fashion website now? What kind of argument is that? Also, why on earth would you use strace or gdb for Java? It has enormously performant debugging tools in the JDK. Also, IDE debugging integration is second to none.
bitwize
"It" factor affects talent pool size. If you're planning a large project and want to hire talent to staff it, how popular a language and framework you choose to implement it in has a direct effect on the cost of implementation. Hint: popular languages and frameworks are far easier to hire for than obscure ones, so unless you have a VERY GOOD REASON not to, it's best to choose a popular language.
toprerules
Because if I'm debugging a critical issues and wading through multiple layers of processes and system interactions, I don't want to have to learn a bespoke toolkit and debugging system for every single process.
briankelly
The tooling is pretty easy to learn if scary looking at first and becoming a JVM expert, at least in the context of GC tuning, might take you a week or less. Some of the defaults are surprising though.

And I think there is some parallel with the kernel vs GC and mmap vs buffer pools - the GC simply has better context in the scope of the application. With other processes in the picture, though, yeah there is some provisioning complexity there.

cgh
Debugging Java is great, as others have mentioned. This includes probably the best remote debugging capabilities available for any platform.

OpenJDK, the de facto standard version used by everyone, is licensed under the GPL version 2 with the classpath exception.

No offence, but you simply aren’t well informed.

PathOfEclipse
I've been working in .NET/C# for the past few years, and while I'm happy with it, I still think the JVM/Java are the best ecosystem overall I've worked in. It's amazing how many things the Java ecosystem gets right that .NET gets wrong.

For instance, Java introduced the fork/join pool for work stealing and recommended it for short-lived tasks that decomposed into smaller tasks. .NET decided to simply add work-stealing to their global thread pool. The result: sync-over-async code, which is the only way to fold an asynchronous library into a synchronous codebase, frequently results in whole-application deadlocks on .NET, and this issue is well-documented: https://blog.stephencleary.com/2012/07/dont-block-on-async-c...

Notice the solution in this blog is "convert all your sync code to async", which can be infeasible for a large existing codebase.

There are so many other cases like this that I run into. While there have been many mistakes in the Java ecosystem they've mostly been in the library/framework level so it's easier to move on when people finally realize the dead end. However, when you mess up in the standard library, the runtime, or language, it's very hard to fix, and Java seems to have gotten it more right here than anywhere else.

deepsun
Interesting. I'm not a .Net programmer, but I always thought .Net takes winning approach from Java ecosystem and adopts it. Java approaches/frameworks are kinda pioneering and competing, while .Net follows and grabs the best. So instead of competing approaches/frameworks (like ORMs for example) .Net has only one, the best one, well adopted and used by everyone there.

But reading your message it doesn't sound like it.

MarkSweep
The thread pool starvation problem in .NET is annoying when you encounter it. Personally I have not bumped into since the .NET framework days.

The thread pool implementation has been tweaked over the years to reduce the impact of this problem. The latest tweak that will be in .NET 10:

https://github.com/dotnet/runtime/pull/112796

I’m not sure a thread pool implementation can immune to misuse (many tasks that synchronously block on the completion of other tasks in the pool). All you can do is add more threads or try to be smarter about the order tasks are run. I’m not a thread pool expert, so I might have no idea what I’m talking about.

cloudking
Why is Java so popular in enterprise?
izacus
Because there was nothing else quite like it at the time most enterprise software was created or recreated.

And it's still stable, fast and reliable with a massive ecosystem of stable, fast and reliable libraries and software. With good developer tooling, profilers and debuggers to go with it. And big enterprise support teams from RedHat, Oracle, IBM, etc. throwing in their (paid) support services.

It might not be the best language in any of the categories (speed - runtime and compile time, tooling, ecosystem, portability, employee pool), but there's pretty much almost no languages that are as good in all categories at once.

And to top it off, JVM can host other languages so it can easily interoperate with more modern takes on language design like Kotlin while still running on pretty much all major operating systems used in the wild and most CPU architectures as well. It'll run on your car's SoC, your phone and on your server. In many cases, using the same libraries and same code underneath.

js8
I believe there were alternatives at the time, but expensive. Java was free and also syntactically compatible with C++. I think that rather these properties (than being somewhat unique) are the main causes of its success.
zabzonk
syntactically compatible with C++

Not. And certainly not semantically.

Pet_Ant
That’s just obtuse. Compare Lisp, Forth, APL, Prolog, Ada, or Fortran. Java is just C++ with a few twists. You can literally write code that will compile in both.
zabzonk
You can literally write code that will compile in both.

An example, please.

Pet_Ant
int fibonacci(int n) {

    if (n <= 0) return 0;

    if (n == 1) return 1;

    int a = 0, b = 1, temp;
    for (int i = 2; i <= n; i++) {
        temp = a + b;
        a = b;
        b = temp;
    }
    return b;
}

...if only the return type was "Crow" then you could .eat() that...

zabzonk
That will not compile with javac, as it is not a method of a class.
Pet_Ant
That code will it just needs to be in the proper context. No the same file will not compile, even if only because javac needs files to end with .java .
int_19h
Java has "unnamed classes" now which makes this work.
js8
That's exactly how I meant it. Another alternative to Java at the time was Smalltalk, with different syntax. Choosing C++ syntax for Java was clearly a marketing move (as it was for C++) - we shouldn't underestimate network effect of familiar syntax.

I think Java succeeded for the same reasons C++ succeeded - built on familiar syntax, reasonably free and "supported by" a large company. Java being a decent language is a consequence of its success more than of its original design.

igouy
Free as in beer, in contrast to proprietary Smalltalk.
hackthemack
I worked in IT from the 90s to today. My perspective is it grew and grew because Sun supported it, then IBM supported it, RedHat supported it. It had the glimmer that it was the "Enterprise Way" of doing "Real IT" programming for "Real Businesses". I am not saying any of that is the "Truth", just the perception that was held by the majority of people who could choose what to write enterprise code in.
fidotron
What was the viable alternative?

Microsoft had C#, at one point IBM pushed SmallTalk. C++ for these environments is doable but going to slow you down at development a lot, as well as being much harder to secure.

At that time the dynamic alternative was Perl, and that remained true basically until Rails came along.

hackthemack
I am not sure. C# came long after Java already made inroads into the Enterprise space. It was a different time.

I would say that many things in IT are not chosen on technical merits alone. You have people that do not want to accrue any blame. Back then, by choosing what IBM endorses or what Microsoft endorses, you absolve yourself of fallout from if and when things go wrong.

Back in the 90s, it felt like IBM, Redhat, Sun kind of, sort of, got together and wanted to keep Microsoft from taking over the Enterprise space by offering Java solutions.

nradov
Right. Before Microsoft created .NET and C# they first tried to play their "embrace, extend, extinguish" trick with Java. They released a JVM and "Visual J++" language which was sort of Java, but had incompatible proprietary extensions to lock customers in to Windows. Eventually they were forced to stop that for legal reasons so they completely dropped all Java support, and built their own replacement virtual machine and associated languages from scratch.
sirsinsalot
And even today some people don't worry about Microsoft's ownership and stewardship of things like Github.
SoftTalker
C++ or maybe Objective-C.

Of course those were much more hazardous languages than Java.

fidotron
Oh yeah, WebObjects! I had forgotten that entirely, and it then transitioned to Java itself.
aaronbaugher
Yes, its early popularity was very much management-driven, based on magazine articles and the like. Its object-oriented design (often presented as if something new) was supposed to make programmers fungible, and its portability was supposed to let you build an app that would run on anything. And it had a Real Corporation behind it, which appealed to corporate management.

In the late 90s, I got stuck making a scheduling program in Java, but it had to run on the 16-bit Windows systems of the time. That was a huge pain, because the 16-bit version didn't have all the capabilities that management was expecting based on the hype. These days, I sometimes have to install enormous enterprise applications that tie up north of 32G of RAM even though they're just basic hardware management tools that would take a fraction of that if built in something like C++ with a standard GUI library. I manage to avoid Java most of the time, but it's been an occasional thorn in my side for 30 years.

toyg
> Sun supported it, then IBM supported it, RedHat supported it

And Oracle (well before the Sun acquisition - in fact, control of Java was basically the main cause of that move).

Any technology that could bag both IBM and Oracle is (or rather was) likely to dominate the enterprise space.

ben7799
Java beta & 1.0 were released my Freshman year of college and I've been writing Java ever since. With the exception of one job where we tried to write a Java-style Enterprise security cloud application in Python every commercial product I've worked on has been built in primarily Java, often times with other languages on the edges of the application.

The key thing I think with Java is the programming model & structure scale well with team size and with codebase size, perhaps even in a way that tolerates junior developers, outsourced sub-teams, and even lower quality developers. All of those things end up becoming part of your reality on big Enterprise products, so if the language is somehow adding some tolerance for it that is a good thing.

The other things around Syntax and such that people complain about? Those are often minor considerations once the team size and code base size get large enough. Across my career there has always been the lone guy complaining that if we did everything in a LISP derived language everything would be perfect. But that guy has almost always been the guy who worked on a small tool off by himself, not on the main product.

Java has changed a tremendous amount as well. A modern Java system has very little in common with something written before Generics and before all the Functional code has been added. Where I work now we have heavily exploited the Functional java add-ons for years, it has been fantastic.

zmmmmm
Consider that in the mid 90's when it arose, most organisations were writing business code in C++ and paying license fees for things as simple as string handling libraries. There was almost no good solution to cross platform network code. RPC calls required things like manually dealing with byte order.

Then most organisations had deployed windows for staff but needed to run things on Sun servers. Java was a god send as a free and actually cross platform solution that let devs work on windows and run the same thing on the corporate server infra without changes. The culture at the time would not consider deploying scripting language sfor full scale applications acceptable, so Java with it's C++-like structure but built in cross platform capabilities and generous stack of batteries included libraries (for the time) was an absolute god send.

lemonwaterlime
Among other things, because the structure of the code corresponds to the structure of the organization itself.

Things tend to form fractal systems of systems for efficiency. A cleanly delineated org chart maps to a cleanly delineated codebase.

keeganpoppen
on one level this is clearly “shipping the org chart”, but… honestly, even as no fan of Java this is clearly efficient on many levels, especially when you consider the humans and org to be part of the system (which everyone should. or it’s just my HCI brain talking.).
j45
Another way to look at it based on coming across it in enterprise:

How did he build something adopted by so many enterprises?

It does some things at scale very well and has been afforded the performance improvements of very smart people for 30y.

It’s not to say the language isn’t verbose, one of my favourite features was the ability to write code in other languages right inside the a Java app pretty well in-line by using the JVM, thanks to JSR-223.

It was possible to write Ruby or Python code via Jruby or Jython and run it in the JVM.

https://www.jython.org/

https://www.jruby.org/

Clojure also runs on the JVM.

https://docs.oracle.com/javase/8/docs/technotes/guides/scrip...

mpalfrey
Decent talent pool.

Decent tooling. Been around for long enough that a lot of the quirks of it are well known and documented. Basically it's a blue collar programming language without too many gotchas. Modern(ish) day Cobol.

(I'm predominantly a Java dev still, even after diversions over the years to Javascript, Python and C#).

locopati
it hits a sweet spot of reliable, C-like, fast enough for most things, with a ton of library/framework support. plus Sun and later Oracle pushed it hard in the 90s/00s. it'll be the new COBOL.
tylerflick
My guess is the size of the talent pool to hire from.
snovymgodym
Because it was in the right place at the right time to supplant C++ and C for application code.
eBombzor
Spring Boot
octo888
It's safe. It's easy to hire anyone from anywhere to write Java. You generally can't create an ungodly mess apart from layers and thousands of classes. There's a library for almost everything. It'll still be around in 10/20 years. It's good enough
whartung
Ode to Java. Boy, I love Java. When I switched jobs way back, a condition was that the new project was going be using Java.

GC. Single file modules. No "forward". The Collection suite. Fast compiles.

The magic of the ClassLoader. The ClassLoader, that was insightful. I don't know how much thought went into that when they came up with it, but, wow. That ClassLoader is behind a large swath of Java magic. It really hasn't changed much over time, but boy is it powerful.

When I started Java, I started it because of the nascent Java web stack of the day. Early servlets and JSP. I picked because of two things. One, JSPs were just Servlets. A JSP was compiled down into a Servlet, and shazam, Servlet all the way down. Two, single language stack. Java in JSPs, Java in Servlets. Java in library code. Java everywhere. In contrast to the MS ASP (pre .NET) world.

Mono-language meant my page building controller folks could talk to my backend folks and share expertise. Big win.

Servlets were a great model. Filters were easy and powerful. Free sessions. Free database connection pools in the server. I mean, we had that in '98, '99.

And, of course, portability. First project was using Netscapes server, which was spitting up bits 2 weeks before we went live, so we switched to JRun in a day or two (yay standard-ish things...). Then, Management(tm) decided "No, Sun/Oracle, we're going NT/SQL Server". Oh no. But, yup, transitioned to that in a week. Month later, CTO was fired, and we went back to Sun/Oracle.

Java EE had a rough start, but it offered a single thing nobody else was offering. Not out of the box. Not "cheap", and that was a transaction manager, and declarative transactions on top of that. We're talking about legit "Enterprise grade" transaction manager. Before you had Tuxedo, or MS MTS. Not cheap, not "out of the box", not integrated. JBoss came out and gave all that tech away. Then Sun jumped on with early, free, Sun Java Enterprise 8 which begat Glassfish which was open source. Glassfish was amazing. Did I mention that the included message queues are part and parcel of the integrated, distributed transaction model for Java EE? Doesn't everyone get to rollback their message queue transactions when their DB commit fails? Message Driven Beans, sigh, warms my heart.

There were certainly some bad decisions in early Java EE. The component model was far too flexible for 95% of the applications and got in the way of the Happy Path. Early persistence (BMP, CMP) was just Not Good. We punted on those almost right away and just stuck with Session Beans for transaction management and JDBC. We were content with that.

The whole "everything is remote" over CORBA IIOP and such. But none of that really lasted. EJB 3 knocked it out of the park with local beans, annotations in lieu of XML, etc. Introduction of the JPA. Modern Jakarta EE is amazing, lightweight, stupid powerful (and I'm not even talking Spring, that whole Other Enterprise Stack). There's lots of baggage in there, you just don't have to use it. JAX-RS alone will take you VERY far. Just be gentle, Java Enterprise offers lots and lots of rope.

None of this speaks to the advances in the JVM. The early HotSpot JIT was amazing. "Don't mind me, I'm just going to seamlessly sneak in some binary compiled code where that stack machine stuff was a nano-second ago. I've been watching it, this is better. Off you go!" Like presents from Santa. The current rocket ship that in JDK development (this is good and bad, I still do not like the Java 9 JPMS module stuff, I think it's too intrusive for the vast majority of applications). But OpenJDK, the Graal stuff. Sheesh, just get all light headed thinking about it.

Along with the JVM we have the JDK, its trivial install. Pretty sure I have, like, 20 of them installed on my machine. Swapped out with a PATH and JAVA_HOME change. The JVM is our VM, the Servlet container is our container. Maven is our dependency manager. Our WAR files are self-contained. And all that doesn't go stomping on our computer files like Paul Bunyan and Blue making lakes in Minnesota.

It's no wonder I was struggling to grok all the talk about VMs, Dockers, and containers and all that stuff folks mess with to install software. We never had to deal with that. It just was not an issue.

I can distribute source code, with a pom.xml, and a mvnw wrapper script, and anyone can build that project with pretty much zero drama. Without breaking everything on their system. And whatever IDE they're using can trivially import that project. It's also fast. My current little project, > 10K lines of code, < 3s to clean/build/package.

Obviously, there's always issues. The Stories folks hear are all true. The legacy stuff, the FactoryInterfaceFactoryImpl stuff. The Old Days. It's all real. It's imperfect.

But, boy, is it impressive. (And, hey, portable GUI folks, Java FX is pretty darn good...)

palmfacehn
Seconded. I'm still using the Servlet API without drama. I click away as soon as I see a package that requires containers to install.
kccqzy
The servlet really is a powerful concept behind a bad name. I've seen more than once where people reinvent servlets in other languages.
Koshkin
Also, λs and μservices...
pjmlp
Gosling primarily uses the NetBeans IDE for development, praising its open source, Apache-licensed nature and dedicated community. He expresses frustration with developers who cling to outdated tools: “The thing that drives me nuts the most are people who are madly grasping the ’80s or the ’70s — people who still want to use Vi, which was high-tech in the ’70s.”

From one of the key developers in the Emacs history, and genesis.

He moved on, others keep trying to live in the past.

lycopodiopsida
Modern stacks (as in go and rust) are largely editor agnostic - it is Gosling who lives in the past, thinking that an IDE is still required(and a very weak one, in case of abandoned Netbeans). One of the reasons, btw, why I would take Go over Java in a heartbeat.
pjmlp
There is hardly anything modern about Go, a rebranded Limbo with with anti-intelectuals mentality.

As for Rust, there is a reason the large majority is either on VSCode or RustRover.

lycopodiopsida
I don’t care about opinions on Go the language, but the tooling around is excellent without being bound to an IDE. And no matter what you use: Goland, VSCode or dape in Emacs, your debugger will plug in the same delve.

the large majority is on VSCode

Here, fixed it for ya. But since when is VSCode an IDE? It is just an extensible editor, not very far from Emacs or neovim. We’ll see how it plays out, but I assume that IDE is a dead concept. No one develops new IDEs anymore, besides the usual money-milking with “Idea + plugin=>new ${name}ide” from Jetbrains.

pjmlp
You mean tooling as it was already kind of available on Turbo Pascal for MS-DOS?

When people discuss Go tooling feels like Renaissance folks resdicovering Roman city enginnering.

VSCode is certainly an Integrated Development Editor, and it is such a dead concept that one of the key Visual Age and Eclipse linage of IDEs is the one behind it, Erich Gamma.

Biggest difference is that one hardly needs to code extensions, or manually configure them most of the time, a simple install button press is only that is needed to get any extension going, many of which graphical, taking all advantage of the Web platform.

lycopodiopsida
You mean tooling as it was already kind of available on Turbo Pascal for MS-DOS?

Spare me your stories of the TurboPascal, I am not a youngster, not easily impressed by name-dropping $some_old_thing and do not care about old men yelling at clouds. You may program in TurboPascal, if you like it.

When people discuss Go tooling feels like Renaissance folks resdicovering Roman city enginnering.

People talk about Go tooling because it is good, lightweight, editor-agnostic, helpful and provided with the language. There are multiple language which fulfil some of the criteria, but not many fulfilling all of them.

VSCode is certainly an Integrated Development Editor

If VSCode is an IDE, then also emacs and neovim and your lamenting has no meaning. And of course, the one behind VSCode is Atom which was heavily influenced by Sublime text.

Biggest difference is that one hardly needs to code extensions, or manually configure them most of the time, a simple install button press is only that is needed to get any extension going, many of which graphical, taking all advantage of the Web platform.

So, basically a neovim distribution? Got it!

pjmlp
Apparently many people need the stories, given how much they boost Go about things that are prior art.

Emacs could be an IDE, if it came with the whole Lisp Machine for the ride, sadly it is only a subset of the whole experience.

VSCode has zero lines of Atom code into it, it started from Azure as Monaco project.

Does neovim distribution handle graphical development plugins, without spawing external windows?

Yeah, right.

lycopodiopsida
Apparently many people need the stories, given how much they boost Go about things that are prior art.

No one but you here cares about prior art. And not even you, most likely, otherwise you would write your in some kind of lisp which was first on most of the things.

Emacs could be an IDE, if it came with the whole Lisp Machine for the ride, sadly it is only a subset of the whole experience.

Lisp is just an implementation detail in (GNU) Emacs, even though it is what makes it a delight to configure. The rest is done, as everywhere, with plugins and built-in package management.

VSCode has zero lines of Atom code into it, it started from Azure as Monaco project.

VSCode has everything from Atom in it, since it is basically a rewrite of Atom, using Electron, which was written for Atom.

Does neovim distribution handle graphical development plugins, without spawing external windows?

What should it be, UML-plugins? Coroner has called, he wants his dead things back. But most stuff is handled with overlays these days with Telescope.

bitwize
Emacs has no "plugins", it's all just Lisp code, all the way down. Big Ball of Mud architecture refined to a state of sublime elegance.

Can I put my cursor on a defun in Visual Studio Code, Eclipse, or IntelliJ, mash C-M-x, and immediately have that functionality available in my running editor session with all my work? I can in Emacs, and that capability has allowed me to smooth out the rough spots in many a workflow.

Lisp is not just an "implementation detail", it's central to what makes Emacs great. GNU Emacs is a running Lisp image, which you can extend and shape at will as you work on something else. A phenomenal tool.

lycopodiopsida
No need to convert me there, I am already in the church.

For programming purposes emacs is not that different from any modern editor - there are some built-in capabilities, the rest you get from ELPA/MELPA/Git. It has no proper plugin arhitecture, which is a gift and a curse at the same time, but mostly works out. Where emacs shines compared to vscode/neovim/etc is that it has a very solid support for prose, org-mode, denote and prots color schemes which are that good. It is why I continue to use it, even though I am not interested in lisp per se these days and could easily replace it for programming with any other advanced editor.

vips7L
You don’t need an IDE for Java either. You can use vscode or neovim, the language server will work just fine. I’ve done both, but eventually moved back to idea (with ideavim).
Kwpolska
He's living in the past, using an IDE that was high-tech in the 2000s.
pjmlp
Ah, that must be why we are getting TUI revivalism these days then.
mark_l_watson
Right on, James Gosling's work is amazing, and he and the whole Java ecosystem have my gratitude: I went to the first Java World Tour conference and wrote a little blog article about it that was linked on Sun's home Java page for about a year. I was very lucky, and since I was the first search hit for 'Java consultant' for a very long time that gave my wife and I the freedom to live in a rural area and I could get remote work for a decade.

As long as I am expressing gratitude, I would also like to call out the Clojure team for developing a wonderful ecosystem in top of Java and the JVM.

It must be wonderful to do work that positively affects the lives of millions of people.

dragandj
Both James Gosling (Java) and Rich Hickey (Clojure) are amazing creators! Each brought a breath of fresh air to programming at their respective times.
jgneff
I am also very grateful to James Gosling. I was working with C++ at Taligent (an Apple, IBM, and HP joint venture) in the fall of 1995 when I first downloaded Java to give it a try. I literally jumped up and down with joy after writing my first "Hello, World" program. It was such a breath of fresh air compared to the Taligent CommonPoint application framework we were building.

I took the severance package when Taligent imploded, dropped everything I was doing at the time, and have been working with Java and its related software ever since.

fidotron
I think it's incredible with hindsight how Java countered many of the mid 90s C++ problems, especially by avoiding multiple inheritance.

It remains a shame that it didn't launch with generics though, and I still think operator overloading would have been good. Had it done so I think a lot more people would have stuck around for when the performance improved with HotSpot.

astrange
I think it's incredible with hindsight how Java countered many of the mid 90s C++ problems, especially by avoiding multiple inheritance.

This is because Java is based on an older language called Objective-C that doesn't have multiple inheritance :)

It's not based on C++, that's just the other OO language from the era people usually think of.

fidotron
This is because Java is based on an older language called Objective-C that doesn't have multiple inheritance :)

No it's not, certainly not any more than it's "based" on Smalltalk.

snovymgodym
Java, especially modern Java, is a fine language. The JVM is an awesome runtime. I'm tired of pretending it isn't.
tstrimple
The vast majority of Java developers will never touch modern Java and have zero idea of its features or capabilities. I'm in the process of migrating literally thousands of servers and tens of thousands of apps to the cloud and there isn't anything close to modern Java. The absolute majority at this client seems to be Java 8 and there isn't a single Java 17 or newer. So it's one thing to have great modern features. But if you're going to be a Java developer it'll take work / luck to actually be able to use decent versions of it. Very similar story with C++. If you're on a great cutting edge team, you might be able to use the shiny new stuff. But more than likely you'll be relegated to some C++11 at the latest.

I haven't seen things quite so bad on the .NET side at this client. Yes there's a ton of legacy ASP.NET apps. But there are also a lot of .NET Core apps. They haven't quite made it to the post Core versions of .NET, but it's still a healthier state than I see with Java. I guess all of this to say that modern versions of "ancient" programming languages are great and really do improve things. But chances are if you're working with an ancient programming language you'll be stuck maintaining legacy shit and won't ever get to utilize the shiny stuff.

This is keeping in mind that your average programmer will never even try to interview for FAANG never mind grind leetcode and programming language trivia for weeks like seems so common here.

dashtiarian
Well to be fair, if you wanted Performance, Linux support, and a framework which was built with dependency injection and async support in mind and not just have them as patched in footguns, you had to migrate to .NET Core. A Java 8 Spring app was just good enough.
LtWorf
If you want linux support, .net is not what you want.

Linux support is an afterthought and it shows. And you never know if it might be dropped next year.

mrcsharp
Wrong. Linux support is first class in .Net just like Windows. We are strictly running our .Net code on linux servers and have encountered 0 problems over the past 5 years.
LtWorf
3 seconds of looking at the API and you see it's not 1st class at all. Presuming you have ever done any programming on linux, that is.
mrcsharp
The API

Which one?

neonsunset
Don't bother: https://news.ycombinator.com/item?id=43396171

These people could not care less about engaging with the subject, they are here because they feel obliged to engage in a moment of hatred of what they think is an enemy tribe.

LtWorf
I mean… I provided justifications and links. The fact that you choose to disregard all of that is on you.

And the bit where you got angry because I didn't reply quick enough on an internet forum shows that perhaps you need to improve your manners.

mrcsharp
Wow what a thread!
LtWorf
the ones dealing with processes are very obviously a terrible match for posix systems for example.
dashtiarian
If you are a .NET shop, .NET core still has a better Linux than Legacy .NET framework hence the migration.

If you are a Java shop everything just works so why touch it?

LtWorf
How do you tell systemd/sysv that your daemon is now ready to accept connections? How do you log to syslog?

In java there's no equivalent to daemon() (unless you go out of your way to call the libc) and java doesn't support SOCK_DGRAM for unix sockets, so no syslog either.

.net seems to have the same issues.

everything just works" is true only for a very very narrow definition of "everything" which leaves out "daemon that works decently
neonsunset
We've had this conversation before, it's likely a waste to reply but, well, my mistake.

For those interested as to why: https://news.ycombinator.com/item?id=43396171

A few more arguments while we're at it:

https://dotnet.microsoft.com/en-us/platform/telemetry (Linux leads with 77% of all systems invoking .NET CLI commands)

https://github.com/dotnet/runtime/blob/main/src/libraries/Sy... (first-class epoll/kqueue integration with async, much like the one Go has with goroutines via netpoll)

https://github.com/dotnet/runtime/blob/main/src/coreclr/gc/u... (GC implementation is cgroups-aware, unlike Go)

vips7L
This just anecdotal evidence of your one client. Every statistic I’ve seen shows that at least half is on a runtime > 8, with most in that half being on 17 or 21. My entire company runs on 21 and will be moving to 25 when it’s out.
aabajian
Just going to remind y'all of this: https://www.joelonsoftware.com/2005/12/29/the-perils-of-java...

I went to a Java school. I remember my operating systems class involved writing simulated OS code in Java (for example, round robin for context switching). The argument was that it would be easier to understand the algorithms if the hardware complexities were minimized. I understand that sentiment, but I don't think Java was the right choice. Python would have accomplished the same task even better (understanding algorithms). I think there was a huge influence from industry to teach college students Java from day one. I had taught myself BASIC and some C back in high school, so it was a bit of a step backwards to learn a high-level language just to do simulated low-level OS programming.

cbm-vic-20
A lot of the arguments Joel makes in that article also apply to Python, and pretty much any other higher-level language that doesn't make you think about pointers. Ironically, he points out the Google had a great leap over Microsoft with MapReduce, which was built in Java.
jonhohle
Back in the early 2000s, I was taught in C, C++, Motorola 68HC11, and MIPs assembly. I can clearly understand how Java works, even if I don’t know its GC is implemented. I can understand how programs were written from the 80s to currently. Had I learned programming in Java or, worse, Python, I doubt I’d have the same understanding. It’s relatively easy to go from low level to high level languages if you’re willing to give up control. My experience is that the opposite is less true. It’s certainly possible, but not as straightforward as understanding some foundational ideas.
telotortium
The original version of MapReduce was written in C++. The successor library, Flume, was however written in Java, but Spolsky would certainly have been referring to the original MapReduce, since the Flume paper wasn't published until 2010.
briankelly
My school started us off in microcontroller programming in C then Java for intro to data structures and OOP then back to C (and MIPS assembly) for systems/OS/concurrency. One thing I appreciate Java over Python for DS/Algo is the clear delineation between abstract data type and underlying data structure - IMO is easy to get a wrong mental model with Python. But teaching OS concepts in Java seems a little crazy to me.
Koshkin
Hm... Why? Java seems to be a perfect language in which to understand things at a conceptual level!
briankelly
Good to get your hands in the dirt as well.
w10-1
Java is a great success story. Though, to be fair, James Gosling was the spark but has not been the steward.

Even as early as Java 1.1 and 1.2 he was not particularly involved in making runtime, library, or even language decisions, and later he wasn't the key to generics, etc.

Mark Reinhold has been the hand's-on lead since 1.1, first integrating early JIT's, HotSpot, the 1.2 10X class explosion, and has been running the team all the way through Oracle's purchase, making the JVM suitable for dynamic language like Kotlin and Clojure, open-sourcing, moving to a faster release cadence, pushing JVM method and field handles that form the basis for modern language features, migrating between GC's, and on and on.

As far as I can tell, everything that makes Java great has come down to Mark Reinhold pushing and guiding.

elric
The whole core team is amazing. Gosling wanted a language that was practical from a development POV. Over the years, it's been refined into a language with a fair amount of mechanical sympathy on top of the development experience. Thanks to folks like Mark Reinhold and Brian Goetz.

I have no love for Oracle the big bad company. But I am deeply greatful they've managed to keep that group moving forward.

selfhoster
Java is a great success story. Though, to be fair, James Gosling was the spark but has not been the steward.

That's like saying Linus was only the spark for git because he spent two weeks hacking it from scratch.

The whole world uses git now.

billmcneale
dynamic language like Kotlin and Clojure,

Kotlin is not a dynamic language, it's statically typed, just like Java.

dreamcompiler
Java frustrates the absolute shit out of me. An objectively terrible language coupled with insanely great garbage collectors, insanely great JIT compilers, and insanely great IDEs.

Why couldn't we have had these things for Lisp?* I mean, if 1/1000 of the intellectual horsepower that's been thrown at Java had been thrown at Lisp, we'd all be driving to work in orbit-capable flying cars that used a teaspoon of fuel per year.

* Of course Lisp invented the insanely great IDE around 1984 but then everybody forgot about it and had to rediscover the idea 30 years later.

asa400
Clojure is around and still going strong! I mean the IDE experience is probably not what you're describing, but you can use the JVM with a mature, productive Lisp language.
dreamcompiler
Fair point.

To me, Clojure is an "almost-lisp" because of its lack of cons cells, its use of all the brackets on the keyboard, and its dependence on the JVM which can't do tail jumps.

I love Common Lisp because it compiles down to the metal and you can write code with it that starts instantly and runs very fast.

But all the above is more about personal taste than anything else, so maybe I should try Clojure again.

asa400
Yeah, I guess it depends on what you want. Clojure is not to everyone's taste, I can respect that. It's a decent option if you have to target the JVM.
kaliszad
The java.net.Inet4Address and Inet6Address could be more lightweight.

For a simple IPv4 address normally representable using 4 bytes/ 32 bits Java uses 56 bytes. The reason for it is Inet4Address object takes 24 B and the InetAddressHolder object takes another 32 B. The InetAddressHolder can contain not only the address but also the address family and original hostname that was possibly resolved to the address.

For an IPv6 address normally representable using 16 bytes/ 128 bits Java uses 120 bytes. An Inet6Address contains the InetAddressHolder inherited from InetAddress and adds an Inet6AddressHolder that has additional information such as the scope of the address and a byte array containing the actual address. This is an interesting approach especially when compared to the implementation of UUID, which uses two longs for storing the 128 bits of data.

Java's approach is causing 15x overhead for IPv4 and 7.5x overhead for IPv6 which seems excessive. What am I missing here? Can or should this be streamlined?

dmurray
What a wonderfully HN response to a biographical piece on James Gosling.

For my part, most of the Java code that I have written that needs to use IP addresses needs somewhere between 1 and 10 of them, so I'd never notice this overhead. If you want to write, like, a BGP server in Java I guess you should write your own class for handling IP addresses.

LtWorf
Java is fast as long as you have near infinite RAM. When you don't it starts breaking apart.

The whole fixation of java developers to abstract things leads to countless virtual calls that are actually very slow at runtime.

rootbear
When Gosling was at Sun, he was one of two principal architects of the NeWS Window system. The X Window system was designed for "dumb" display devices and so the display elements were all static, not requiring much work from the server. NeWS was designed to run on a (Sun) workstation, where there was a lot of computational power available, so it was based on Postscript. A NeWS client would send a program to the server, not just static commands.

Gosling, unsurprisingly, designed Java with the NeWS model in mind, where web pages were programs, not just static HTML documents. When I got him to sign my copy of "The Java Programming Language", I asked him if Java was the revenge of NeWS. He just smiled.

bitwize
Just as we have a modern successor to X in Wayland, we also have a modern successor to NeWS: the browser with JavaScript, with PWAs and Electron providing a smoother desktop integration.

I wonder what Gosling thinks of the fact that NeWS ultimately won in the end, even on Microsoft systems.

AStonesThrow
The corollary of this was Display PostScript. At my first job we had a SPARCStation 2 with a SPARCprinter. The SPARCStation was a mighty wonder to behold, with a storage pedestal and a lovely OpenWindows GUI on a luxurious Sun monitor and color framebuffer. The operator sitting at the desk was often just a novice clerical worker, but we ran a few Internet services on the machine as well. However, our department depended on that SPARCprinter to spit out hundreds of sheets of paper daily.

We could not depend on the printer to stay functional, though. Have you heard of a Winmodem? SPARCprinters were essentially that: they were configured as a "dumb display device" where all the imaging logic was contained in the software and run on the server. A page was written in PostScript, rendered on the print server, and dispatched to the printer as if it were a framebuffer/monitor.

Unfortunately, for whatever reason, the server software was not so reliable, or the printer hardware wasn't reliable, and because of this peculiar symbiotic parasitism, whenever our printer wedged, our server was also toast. Every process went into "D" for device wait; load averages spiked and all our work ground to a halt. We would need to pull the worker off the desktop, reboot the whole server, and start over with the printer.

That printer haunted my dreams, all though my transition from clerk, to network operator, to sysadmin, and it wasn't until 2011 when I was able to reconcile with printers in general. I still miss SunOS 4 and the whole SPARC ecosystem, but good riddance to Display PostScript.

voidhorse
The java ecosystem is great, and the JVM does deserve the appellation of technical marvel, Java the language on the other hand...questionable.

Many of Java's novel language choices have proven unfavorable in the long run (e.g. everything is a class, and even its syntax was needlessly verbose and ceremonious from day one) and all of what makes it a halfway decent language these days are good ideas that originated in other languages, often eons ago, which Java, for some reason, often elects to rebrand with its own terminology.

That said, the maintainers also do a phenomenal job managing the evolution of the language and preserving compatibility, but from a pure programming language design standpoint it's largely a messy amalgam of great ideas from a bunch of other places awkwardly realized. Great, robust ecosystem, great platform, great management, mediocre language design.

lkuty
I am wondering what was the role of Guy L. Steele in the creation of Java if he had any. From the article, it looks like it was Gosling alone. I did not cheat by checking on Wikipedia
steelbird
He worked on it after, no?
nunobrito
Oh, this marks 16 years that I'm writing Java in that case.

My only complaint is the flop with JavaFX. It should have remained as part of the JDK to replace Swing and continued development there.

Without that, Java is thrown as the forever backend platform.

Anyways: good interview.

jcadam
Been coding on the JVM for a good chunk of my career. Though the last several years has been in languages other than Java - Scala, Clojure (my personal favorite), and Kotlin.

Finally managed to get a job offer (after being unemployed for a bit) doing Python. It's starting to look like demand for JVM experience is beginning to wane. Might be time to move on anyway :shrug:

I'm old... as long as there's a steady paycheck involved, I'll code in whatever language you say.

Though, currently working on a little personal project in Scala. :)

neom
James Gosling, Robert Pike and Geoffrey Hinton are my top 3 "Canadians who meaningfully changed things in technology" (tho, I should probably make it a top 5, add Brian Kernighan and figure out someone else)
cmrdporcupine
Kenneth Iverson (APL) could be your fifth even if none of us use APL, its reputation and influence is probably deeper than we realize
throwaway7783
Java stagnated for a while, but has now picked up steam. With things like GraalVM, the stellar ecosystem, generally very good performance and changes to the language, it is more and more pleasant to use.

It may not be cool to use Java for startups, but we do and are immensely productive with it.

ta12653421
i can just say:

being now older (40+ ;-), i would suggest to just use the tool that gets the job done.

in todays world, this is Java or C# - while im highly advocating for the latter, because the eco system feels much more tightly integrated: i can spin up whatever application for every usecase with C# in 1 minute; also the language still evolves massivly, there is enough HR-power on the market, also .NET is now crossplatform.

the language is just elegant and very efficient, it makes the job much easier

lysace
The JVM was the first VM I got to know, at uni in like 1996 or so. Had fun building stuff using the Jasmin "assembler". Seems like it's on Github now: https://github.com/davidar/jasmin

Jasmin was written because, at the time that we wrote the Java Virtual Machine book for O'Reilly, Sun had not published an assembler format for the Java virtual machine.

Generating a binary Java .class file is pretty fiddly. Its like creating an a.out (or .exe) file by hand. Even using a Java package like JAS (a Java API for creating class files, used internally by Jasmin and written by KB Sriram), you need to know a lot about the philosophy of the Java Virtual Machine before you can write something at the Virtual Machine level and generate a Java class.

We wanted something that made it very easy for a student or programmer to explore the Java Virtual Machine, or write a new language which targets the VM, without getting into the details of constant pool indices, attribute tables, and so on.

theanonymousone
I have heard it about the situation in 1995, but it probably also holds to a good extent now: You appreciate Java (only) after you have experienced/experience other languages.
klim2media
My biggest gripe with Java is the only really viable IDE option is from a for-profit company and that it routinely gobbles up my RAM. I used Eclipse and Netbeans back in the day but IntelliJ is superior before it becomes unusable.
rr808
Java is completely revitalized now and is my favorite platform.

The main problem is the legacy code and attitude out there, dependency injection, using Spring or Spring Boot etc SUCKS. VertX is/was good but now with virtual threads you dont need all the async complexity.

geodel
Growing up with “pretty close to zero money,”

Zero money programmers >> Zero interest rate programmers :-)

jbellis
On my list of programmers I want to meet before it's too late, along with Brian Kernighan.
kubb
Worth remembering how much marketing effort and money there was in pushing Java in the 90s:

https://m.youtube.com/watch?v=NVuTBL09Dn4

SoftTalker
Gosling also developed a version of Emacs back in the early 1980s.

https://en.wikipedia.org/wiki/Gosling_Emacs

Gosling Emacs was especially noteworthy because of the effective redisplay code, which used a dynamic programming technique to solve the classical string-to-string correction problem. The algorithm was quite sophisticated; that section of the source was headed by a skull-and-crossbones in ASCII art, warning any would-be improver that even if they thought they understood how the display code worked, they probably did not.
kazinator
Mr. Gosling; please hunt down and release the source code for Ace: a syntax-driven C preprocessor.

You can keep the Java, thanks.

zombiwoof
Legend