back
184 comments
For a better GC experience, stop stopping the world and stop sharing mutable state.

ORCA (and Pony language) solved this while allowing selective mutability and zero-copy message passing improving on Erlang HiPE/BEAM by tying objects to a tiny heap with individual actors (cooperative async threads). There is no global locking in Pony except in limited circumstances.

Zulu C4 is an improvement. Schism and Metronome are less pausey but slower overall.

https://www.azul.com/products/components/azul-zulu-prime-bui...

https://dl.acm.org/doi/10.1145/1809028.1806615

https://researcher.ibm.com/researcher/view_group_subpage.php...

How do you to zero-copy message passing if you have one heap per actor? Or am i misunderstanding and a couple of actors share a heap, but there is no giant heap?
Has anyone ever tried to port OpenJDK's fancy garbage collectors other runtimes? I guess often GCs are quite intimately tied to other details of the runtime and specialized to code patterns and use cases of particular languages, but still, would be interesting to hear about attempts.
That would be difficult. The GCs share a lot of code, and have a lot of code to deal with Java specific things like class unloading and soft/weak/phantom references. It's easier to run other languages on top of the JVM runtime, which is what projects like Truffle and JRuby do.
> I guess often GCs are quite intimately tied to other details of the runtime and specialized to code patterns and use cases of particular languages

This is why I don't understand the WASM GC proposal, which I understand to be an attempt to make a GC that works for all languages. Can you really write a GC that performantly supports both Java and Go given the different tradeoffs/approaches each makes with respect to memory management, layout semantics, etc?

AFAIK, no. The opposite is true with MMtk (https://www.mmtk.io), which is a toolkit with many GC algorithms implemented that has been plugged into other runtimes, including, as it happens, OpenJDK.
I've wondered how feasible this would be. In general, I think the other commenters are correct that GCs tend to be intimately tied to the runtimes. But the JVM now has an interface for garbage collection (https://openjdk.org/jeps/304), which might make the GCs easier to extract and use in other projects. I'm not aware of anyone trying though.
Someone ported the G1 collector to JikesRVM [1], a research Java VM. It's not a production case-study of course, but interesting nonetheless.

[1]: https://users.cecs.anu.edu.au/~steveb/pubs/papers/g1-vee-202...

Other runtimes also have fancy GC, JIT and AOTs of their own.

That is the cool thing about having multiple implementations.

Is there a good guide to learning modern Java? At my workplace, we’re thinking about using it for a few things from Python. I’m not looking for a “Java for Python developers” but more like “Java for people who already know about the basic structures of programming languages”. I would love to hear about variable instantiating and for loops as little as possible to grok the Java model of programming, then drive right into the meaty bits of how Java programmers think today. I did Java 20 years ago in college.
I recommend The Core Java pair of books by Cay Horstmann, supplemented by Effective Java by Bloch. Those are probably the two most authoritative sources on Java out there, and both highly readable.

I heard not so good things about Herb Schildt's book.

Effective Java by Joshua Bloch is fantastic for covering up to Java 9. There have been incremental updates since then but this book will get you 95% of the way, and it is very well written.
Other have great recommendations. Two of mine:

1. The Java Programming Language book:

The K&R of Java

https://www.amazon.com/Java-Programming-Language-4th/dp/0321...

2. Zantorc's videos: https://www.youtube.com/@Zantorc/

He really gets into the nitty gritty. You can listen to this while commuting, etc; Just finish 1 video per 3 days, say. It adds up quickly.

Have you ever heard of the book Core Java for the Impatient?
"Java for Developers Pocket Primer" is a new book that ramps you up fast (~200 pages) assuming you are already a developer familiar with programming.
In 2023 don't write java but kotlin code.
Now in 2023 I'd strongly think twice before investing heavily in Java. For the vast majority of use cases where Java is utilized Go ends up being a better choice w/ cleaner codebases, static binaries (none of this JDK/JRE deployment mess), and phenomenal performance. Not to mention proper interop with native (C/C++) code without JNI funny business.
Is there a good decision flowchart on how to chose GC for a particular task/application?
Always start with the question, do you need to optimize? :) Most likely, Probably not! Java is _fast_, and the JVM is pretty good at what it does; 95% of the time merely checking for GC thrashing is all that’s needed.

Otherwise, start with G1 and get your Xmx value in the ballpark. VisualVm can help you determine if you're thrashing. Are you GCing like 10+ times per second? Keep an eye on it. If you start hitting giant pause times and 50+ collections a second, you've got problems :) Increase Xmx. (and no, please don't set Xms = Xmx).

If you have issues past that, it’s not the garbage collector that needs help; the next step is to audit your code base. Bad code makes any Garage Collector in any language to misbehave.

For instance, are you `select *`ing from a table then using the Java streams api to filter rows back from a database? That will cause GC issues :) fix that first.

So now if you've got to this point and you still need to optimize, what we've done is just run through the different collectors under load. One of our JVMs is a message broker (ActiveMQ 5.16.x) and we push a couple thousand messages per second through it. We found that Shenandoah actually improved latency for our particular use case, which was more important that throughput and outright performance.

Oh, and if your application and usecase is _extremely_ sensitive to latency, forget everything I wrote and contact Azul systems about their Prime collector. They're pretty awesome folks.

Oracle has an overview here [0]. But in general I would say unless you're facing an issue just to let the JVM pick the GC and only really tune -Xmx

[0] https://docs.oracle.com/en/java/javase/18/gctuning/introduct...

I think generational ZGC is going to be the "sane default" soon.
single-core, latency doesn't matter, low footprint: serial

throughput: parallel or G1

balance between latency, footprint and throughput: G1

latency more important than throughput or footprint: ZGC or shenandoah

missiles and HFT: Epsilon

How much memory can you use for a Java app?

My java/kotlin app needs to keep a big table fully in memory. (~10 million records). And it is reloaded about 3 times a day. In C, I would just malloc the whole table in one chunk. Perhaps there is a specialized GC for this usage ?

There's no particular limit to JVM, you can use all available memory if you like.

For best performance you can decompose your structure to primitive fields (int, float, char, etc) and create array for every field. So you have, say, 10 arrays with million items each. Instead of creating one array which holds pointers to another 10 million objects on the heap. It gets tricky with strings (you need to flatten all strings into a giant char[] array and keep two arrays with index and length data, but doable.

Though 10 million of records might be OK for JVM. Measure your GC times.

I'd suggest to hide implementation details behind API, start with ArrayList<MyRecord> and refactor it later if needed.

It depends if your VM is native or not. Ex: https://www.graalvm.org/
How much memory? ZGC is made for multi-terabyte heaps.
What's wrong with newing the whole thing? Or even the fully naïve solution of newing as needed?
Do people follow GC research at all 'for fun'? Any places/sites/people to pay attention to for the latest and greatest goings-on that may show up in production x years from now?
I do follow Loom 'for fun', lurking the mailing list archives [1]. You can definitely do the same for GC implementation [2] (general topic list here [3]); but it may not talk a lot about external initiatives like Shenandoah.

Beware that you're gonna have to filter a lot! There's patch merging and very low detail implementation conversations. For example, you'd be pleased to know that G1 can now skip a guard in card-table clearing [4]. Don't ask me what is the card table and guards and why do you need to clear it, though.

One thing I'm looking for in GC advances is new hardware support for it in RISC-V J extension. There's gonna be memory tagging (helping security and memory management in GCs), and pointer masking (hardware support for what ZGC does under the hood)[5]. But we're probably a good 5 years away from seeing that in real life, if ever.

[1] https://mail.openjdk.org/pipermail/loom-dev/

[2] https://mail.openjdk.org/pipermail/hotspot-gc-dev/

[3] https://mail.openjdk.org/mailman/listinfo

[4] https://mail.openjdk.org/pipermail/hotspot-gc-dev/2023-March...

[5] https://github.com/riscv/riscv-j-extension/blob/master/point...

We try and aggregate content from the GC team here [1].

[1] https://inside.java/tag/gc

I am interested in this area too, but I don't know of any single place to follow it all. I have found that there isn't an avalanche of "new" stuff, but a lot of different ideas with different tradeoffs that change in relevance based on usage patterns, languages/runtimes, and hardware characteristics.

Besides the JVM resources linked by others, I found Richard Jones's "Garbage Collection Handbook" to be a decent introduction for background [1]. The Go team has written a bunch about their GC approach [2] - it is really interesting to see how it compares to the various options in the JVM and under which scenario you might prefer one or the other. And occasionally there are interesting articles on arxiv.

1. http://gchandbook.org/

2. https://go.dev/doc/gc-guide

Sure, I follow it but HotSpot is state-of-the-art, so if you follow that team then you're basically following GC research already. There's a little to be found in academia, but only rarely these days. The implementation cost to get to the cutting edge is too high.
Yes, it is a cool thing when one is into compilers.
Love Java. Very much looking forward to LTS Java 21. <3
There are so many huge features in Java 21, especially around scalability and data handling - I feel like it may be a watershed moment that brings Java back to the forefront as a leading choice for heavy lifting, data focused work. As an LTS release I could see it forming the next long term baseline that people build on for a very long time.
In the world of web development why would one pick Java(or Kotlin) over TS/node.js ?
> thread-local allocation buffers (PLABs)

:-/

mind to expand?
Off-topic but about Java generally:

Java is such a storied and long-running and used-almost-everywhere language especially in Data Engineering (see all the Apache Data Eng projects like Calcite, Hudi, etc) but I just find it soooooo verbose and everything being a class and having to override things ugh .. it's all the things I hate about OOP in the forefront.

One of the goals of Project Amber [1][2] is to move the language towards a more data-oriented programming model. With Records, patterns, sealed classes, etc., it should feel much less verbose over time. And unrelated to your concern but addressing some of the learning overhead, see Paving the Onramp. [3]

[1] https://openjdk.org/projects/amber/

[2] https://inside.java/tag/amber

[3] https://openjdk.org/projects/amber/design-notes/on-ramp

As the classic saying says: there are languages everyone complains about and languages that are not (actually) used. Verbosity is usually a _good_ think especially in large code bases with large number of people (where every successful startup will eventually get)
I've returned to Java after using Clojure and Groovy for several years. I appreciate the fact that Java's just plain boring and slightly verbose.

Most of the time the complexity in my code has little to do with Java being verbose and more due to the business problem. There are areas to improve and Java's been making great strides recently. For example, in Java 21 we may finally have methods like getFirst() and getLast() for lists (via JEP 431) instead of the incredibly clunky list.get(list.size() - 1). Java also recently added multi-line Strings and templating is coming shortly. Streams and Optionals also reduce quite a bit of boilerplate, e.g. Optional's map and ifPresent methods are often elegant. Really I can't think of many other areas where Java gets in the way. Our team is incredibly productive with modern Java.

I think most developers actually write overly verbose code regardless of the language. And it seems little to do with years experience. This youtube channel covers most of the basics:

https://www.youtube.com/@CodeAesthetic

To me I just follow these recommendations naturally but in most PRs I review there's often huge amounts of overly nested code, poorly named methods, etc.

Going from Java 8 to Scala was mind melting. Would never want to go back. Though I’ve heard later versions of Java are better. And katlin seems like an in between.
So your (general) complaints are all you do add to this when others try to create things to help others?
Agreed. Reading and writing Java code just really annoys me. It's so ugly, in my opinion.
Just try something else.