Hacker News new | past | comments | ask | show | jobs | submit login

As Java is generally the fastest GC'd language, what's the current state of Java gamedev?

Once upon a time, this indie Java game called Minecraft became the most successful game of all time.

But from the few minutes of research I just did, Java cannot be deployed to many commercially important systems

  - Nintendo Switch
  - PlayStation
  - iOS
It appears Java is only still viable for Windows and Android, and the 1% Linux desktop market.

There used to be the GCJ project which would in theory let you run Java anywhere you had a C/C++ compiler, but Oracle's litigiousness killed that because the Java[TM] "platform" must run the official Java[TM] bytecode.

It appears C# via Monogame lets you deploy to all desktops (Win/Mac/Linux), mobiles (iOS/Android), and consoles (PS/Switch/Xbox). So ironically C# seems to now be the "write once, run anywhere" fulfillment of the original Java promise.

[EDIT: grammar.]

Java's FFI and value type situation are the two major missing pieces for Java gamedev. C# has better stories for both, and has from the beginning.

Don't confuse Java having the fastest GC with Java being the fastest GC'd language (especially not in all situations)

> Don't confuse Java having the fastest GC with Java being the fastest GC'd language

I've always wondered, it's likely that Java has the fastest GC because it needs to have the fastest GC, otherwise it would be a bottleneck. Other popular languages probably don't depend as much on the performance of their memory allocation primitives.

Good point, the Debian Benchmarks Game for example shows C# matching or considerably beating Java at everything except the binary trees benchmark which stresses GC/mempool performance.


I haven't tried C#/MonoGame yet but all this discussion is considerably warming me up to it. The recent extremely successful indie game Hades was made with MonoGame.

Microsoft in typical MS fashion makes MonoGame higher friction if you aren't using a Windows box for development with MSBuild. On Linux it appears you need to use Wine to run DirectX effect compilation, though once compiled it works on OpenGL backends:


Thats cause most of the C# implementations in the benchmarks game are just calling into C libraries. For example the regex benchmark:

     [DllImport("pcre2-8", EntryPoint = "pcre2_compile_8", CharSet = CharSet.Ansi)]
        extern static IntPtr PcreCompile(string pattern, long length, uint options,
            out int errorcode, out long erroroffset, IntPtr ccontext);

I just looked at the F# vs Java benchmarks and .NET is still faster on most of them just to get a sample on more idiomatic code. The F# codebase doesn't use a lot of externals looking at the code list


Only the PiDigits benchmark uses "extern's"; only because it seems like a lazy port. Everything else is native F# code. It beats Java in all benchmarks expect for the binary-tree one. To see a functional language match or beat benchmark level Java on many cases, at least for me, feels kinda nice. Many other real world benchmarks in house (tech choice evaluations) and third party I've seen JVM vs .NET Core also show .NET usually coming out on top recently.

The .NET GC isn't as good as the Java one. But I feel that's because the cost/benefit of improving the CLR's GC is less than Java's so the work is put elsewhere. The language (C#/even F#) generates less garbage in the first place with typical code. Any GC improvements there probably don't have the same bang for buck as in Java where allocations IMO are more frequent in day to day coding.

There was an article ages ago I read about the rewrite of C#'s Dictionary to the new generic one that went from being reliant on allocations in the older releases (C# 1.0 didn't have generics so iirc it behaved more like Java's) to using a generic struct array.

Doing so cut down the number of memory allocations to _3 allocations_ from something like _2 * N allocations_ (N being the number of elements in the map).

The improvement in performance was apparently staggering when it came to lessening the GC pressure. (Sadly I couldn't find it with a quick google).


Reified generics avoid a lot of "boxing" that comes with standard Java, and that's only one of many features there that helps. Its just easier to avoid allocations in .NET in general over Java IMO. From recent articles and improvements to the platform the team spend their effort to reduce allocations in the first place equal to trying to improve the GC (e.g. ValueTask over Java/Scala futures, etc)

2 out of 10 tasks regex-redux and pidigits accept third-party libraries, the other 8 out of 10 tasks do not.

FYI, Hades was ported from C#/MonoGame to C++ late in development in order to ship on Switch. Their previous titles (Transistor, Pyre, etc) were C# from start to finish though. AFAIK some of their releases use FNA instead of MonoGame (a similar library with more of a compatibility focus.)

Great catch! The Wikipedia article for MonoGame lists Hades, but is evidently wrong. Hades used The Forge for graphics. Ctrl/Cmd-F "Hades" on the Github page has some info:


The Forge is graphics only; audio, input, etc., have to be handled by something else and Hades used a custom C++ engine apparently.

Wow, first time I've heard about Monogame, I wonder how it'd compare to Godot.

So I just tried to set up MonoGame as a result of this thread, but with a twist: only use non-Microsoft servers as sources, to see if it really is 'open source'.

It's impossible.

I just spent 30 minutes trying to find a single non-Microsoft mirror for the .NET Core dependency. If MonoGame is your Spice Melange then Microsoft's servers are the planet Arrakis, the only source in the known universe.

On Ubuntu you need to add a Microsoft server as a repo, you can't just "apt-get install dotnet-sdk-6.0".

So, yeah, MonoGame is not for me. I'll stick with Godot or SDL2.

This is absolutely true. When I turn kitchen upside down while making one simple dish. Cleaning up fast afterwards is not my awesome superpower, its bare minimum necessity to live amicably in house :-)

Java’s new better FFI is almost ready with project Panama and value types will come, but it is exceedingly hard to retrofit into a language (but the idea for the exact semantics might have formed already!)

Project Panama should greatly improve the FFI & game dev situation greatly.

For native binaries, we now have https://www.graalvm.org/reference-manual/native-image/, but it probably doesn't yet work nicely with game frameworks? Not sure.

There are some engines, frameworks: https://jmonkeyengine.org/, https://litiengine.com/, https://libgdx.com/, https://www.lwjgl.org/.

But I have no real experience with any of those.

My (admittedly not huge) experience with Quarkus would tell me that GraalVM is nowhere near ready, most specifically because of reflection.

You either plan your work around zero reflection Java or pray to whatever god that your code passes.

At that point why even bother with Java or native images.

So I just spent some time looking at all of these you listed. With the exception of libGDX they are all essentially desktop-only (Win/Mac/Linux).

LibGDX appears to support iOS/Android and HTML5 desktop browsers, but not consoles (Switch/PS/Xbox).

I’ve used libGDX. Porting to iOS/Android/HTML5 is honestly a pain.

iOS is actually not that hard, I got it to work using RoboVM, but you have to do some research because the documentation is outdated. HTML doesn’t work with Kotlin because it compiles directly from Java, and because it compiles directly it probably has some extra quirks.

No official support (console makers other than MS are making things a PITA) but Robotality has ported their Pathway game (Based on LibGDX) to the Switch.

You can on iOS, for example with Codename One or Gluon Mobile,



They are also quite happy to sponsor possible console ports.

Seriously, with sub-ms pause times of ZGC you could run a GC every frame and have tons of time to space for actual processing.

It sounds very nice but if more than half an indie game's revenue comes from Nintendo Switch then you need a low friction way to get your .java files running there. You also need a proven audio mixer stack so you can load background_music.mp3 and play bang.wav and boom.wav without any popping or leaks. Right now Java seems sort of iffy on consoles, as in, you could maybe spend a ton of time and/or money to get an effort like GraalVM production-grade working there, but no one has bothered to do it yet. It seems to be much lower friction to just use C#/MonoGame, or SDL2 with your scripting language of choice that compiles with a C/C++ compiler, or a proven game engine.

A pause does not correspond to a full GC, of course. The work of GC is split into a lot of concurrent work and a lot of really tiny pauses on each application thread. The entire GC cycle might be split over hundreds or thousands of tiny pauses and take many seconds--there's just no particularly big pause. During the GC cycle the application is still running and allocating, and there is enough slack space that it doesn't run out of memory before the GC cycle finishes and transparently adds freed memory back into the usable pools.

It would be great if the whole cycle were that fast! But alas, there simply isn't enough memory bandwidth to GC 128GB of memory in 0.1 millisecond :)

That's fair, although you're not free()'ing 128GB in 0.1ms either :)

The amortized cost of GC is more efficient that malloc/free, but it's traditionally not good for latency sensitive systems due to long pause times causing jank/dropped frames. Now that GC algorithms like ZGC have advanced to give sub ms pause times, you no longer have that worry.

Technically we didn't need ZGC for this to begin with. IBM launched metronome a while back for real-time systems, but it was never as widely available as ZGC.

In a game you should keep allocations during gameplay to a minimum anyways, malloc() is not O(1) is has variable runtime based upon the current layout of free memory. Additionally, long running malloc/free based applications have unfixable memory leaks due to memory fragmentation.

In my opinion there's very few cases where you should be dynamically allocating memory, and not using a garbage collector.

> That's fair, although you're not free()'ing 128GB in 0.1ms either :)

Well I guess that's not technically true, free() could very well be a quick operation if you have a single 128GB object.

You can compile to iOS/Android with libgdx.

I've been doing this with a game I'm building that has a custom 3D OSM map renderer.

Well, Minecraft is notoriously slow, but I guess that's very much nothing to do with Java, but the un-optimized code... Have seen quite some developers criticizing Mojang for this.

Is it really, though? Just for kicks, last year I got an ibook g4 for a few dollars, and I got Minecraft running on it, not the absolute latest version, but one a few years old (Minecraft dropped 32 bit LWJGL support a bit ago). With some tweaking, I managed a solid 40-50 FPS, on what would have been a pretty anemic processor back in ... 2002, 2003?

Although, maybe it doesn't count as I used mods like Optifine, which are made to ... replace said un-optimized code, but I thought it was a good showing for Minecraft and the JVM anyway.

Minecraft itself it good enough for... pure Minecraft gamplay most of the time.

But it can overwhelm itself. There's a equipment called Elytra you can wear to slide down the air, and if you use Rocket when sliding, you gain a huge momentum boost.

If you keep boosting on a server, being fast enough to challenge the serverside world-loading, you can crash the server.

Another big defect is it's rendering is deeply tied to cpu time, and the game itself has limitation. My recent experience with a 200+ mods & shader setup is that with RTX3080TI (also better cpu) and GTX980TI it runs at same fps (20~30).

> but I guess that's very much nothing to do with Java, but the un-optimized code

You guess right. There are some few fan made mods (optifine, sodium/etc) that often improve performance by an order of magnitude, from tens of frames a second to hundreds.

Minecraft Bedrock, which is written in C++, runs dramatically faster than Minecraft Java. (That's the impression I get from the comparisons I watched on YouTube at least.)

It's a shame for Java since the increase in render distance makes the game much more immersive.

Lack of mods is a big problem...

Did Java already beat Common Lisp and C#? I doubt so. Esp. since the commercial lisps with much better GC's are not listed on the benchmarkgame. But also not Shenandoah, and the other commercial Java GC's

> As Java is generally the fastest GC'd language, what's the current state of Java gamedev?

In my eyes, there are no truly viable options out there, mostly due to a lack of approachable GUI game development software or toolkits.

For example, compare the one option that comes close, jMonkeyEngine (https://jmonkeyengine.org/) to the likes of Unreal (https://www.unrealengine.com/en-US/) and Unity (https://unity.com/), or even Godot (https://godotengine.org/).

Sure, many out there enjoy developing games in a code first approach, or even writing their own engines (e.g. Randy, whose videos are pretty interesting and comedic: https://www.youtube.com/c/RandytheSequel/videos or https://www.youtube.com/c/RandallThomas/videos), but i'd argue that the success of an engine largely depends on the popularity that it gains, which is largely influenced by how easily approachable it is.

Java game development doesn't have such a tool or set of tools, even the activity on jMonkeyEngine's GitHub (https://github.com/jMonkeyEngine) is really low, compared to that of Godot (https://github.com/GodotEngine), even if the technologies themselves could be used to similar degrees of success in many situations.

Come to think of it, it would be nice to actually benchmark something like Unity (C#), Godot (C#), Godot (GDScript) and jMonkeyEngine (Java) in similar real world applications, to see how they fare, performance, resource usage and development speed wise.

My intuition tells me that Java would be faster than GDScript, which would make talking about its (and also Java's, and thus also C#'s) performance a moot point for many of the indie games out there, since GDScript's slowness doesn't prevent many wonderful games from being developed in Godot, here's their latest showcase reel: https://www.youtube.com/watch?v=iAceTF0yE7I

Is Java GC (“the best”) really that much better than something with immutable heap ie Haskell?

I love functional languages but is anyone actually using Haskell to develop for Nintendo Switch and PlayStation? Can you use Haskell on the Nintendo Switch to access a robust audio mixer stack?

F# can be used with C#/MonoGame which seems to run well everywhere so that's one route to functional programming gamedev. Another route appears to be to use SDL2 with a functional language that supports ANSI C bytecode runtime fallback. E.g. OCaml has a bytecode compiler and an ocamlrun runtime that can be compiled with an ANSI C compiler. But I don't know what the GC latency guarantees are for the bytecode runtime. OCaml's native low latency GC benefits from Jane Street's contributions because Jane Street uses OCaml for high frequency trading. But bytecode OCaml running on Nintendo Switch isn't the same thing as native Linux OCaml.

I don't think that anyone is using Haskell to develop any serious games yet.

The toy demos are quite elegant, although the community is probably lacking a good scene editor ie Godot or Unity.

Edit: godot-haskell exists, but it's still a little edgy.

For what it's worth I've had a good experience doing gamedev in Scala using LibGDX. (Though not on consoles, and not pure FP)

> It appears Java is only still viable for Windows and Android, and the 1% Linux desktop market.

Funny how you frame Java "only" being available for some of the most popular platforms, which is billions of devices.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact