For example the Go runtime and I think C# as well are written in their respective language.
For example the Go runtime and I think C# as well are written in their respective language.
Some of the reason is historical, and some has to do with warmup. Project Leyden and Graal's Native Image will help compile more Java AOT, allowing even more of the runtime to gradually be written in Java. It will take some time as it's not a top priority: it won't immediately deliver user-facing functionality, and most of the work on the JDK is already done in Java code anyway.
By the way, the .NET CLR is AFAIK written in C++, like with Hotspot. It's not fully self-hosting.
It's a tricky process because HotSpot is highly performance sensitive code. People won't accept regressions just to convenience the JDK maintainers. Java meanwhile is deliberately a simple language to make it accessible for people, so you lose some low level techniques that are useful for performance. Nonetheless, GraalVM native image has proven that you can achieve HotSpot like performance with a JVM written in Java. However it requires a big change in the compilation model that isn't always appropriate.
I can't quite imagine how you'd bootstrap something like that.
See Scheme48 or Go. There are some ways around that bootstrap problem.
That's what it does.
With Graal, it's possible to write a JVM in Java, but the JVM doesn't depend on another JVM to run, and the way it runs bytecode isn't the way it was compiled in the first place. It's not really self-hosted in the same way that a compiler can be.
It's like how PyPy is Python but with the asterisk that it's bootstrapped with RPython which is an almost-subset of python so that it doesn't require a runtime.
You could define a statically compilable Java subset (like that which gcj used to accept) and build a runtime in that which would mean omitting features such as reflection but a lot of defacto standard java tooling like Spring Framework would not be compatible.
But the JVM you build using your statically compilable Java subset can then run the Spring Framework or whatever.
How restrictive do you think the subset is? It only doesn't support some features you probably never wanted to use anyway, and arbitrary reflection. I maintain 125k lines of Java that conforms to the subset rules, and to be honest I never even think twice about the fact that it's a subset.
There are a couple of Java implementations written in Java, Jikes RVM being one of the first ones, almost 15 years ago.
GraalVM is the evolution of MaximeVM, originally developed at SunLabs, also about 15 years ago.
BTW, how do you implement a garbage collector with a garbage-collected language?
You write it carefully so the garbage collector itself doesn't also need to allocate objects.
Here's a GC for Java written in Java https://github.com/oracle/graal/tree/master/substratevm/src/....
Java doesn't provide a primitive to deallocate memory. So while I can see how for instance allocation a huge chunk / big array could be allocated and you represent objects in there don't you end up with a situation where your process will always occupy a fixed amount memory? Might not need to be fixed. You might also be able to extend more but how would you free that again?
But you might find this interesting as a specific example - this is where it actually obtains memory from the OS.
https://github.com/oracle/graal/blob/44e68777b130c8ee781c72b...
Note the @Uninterruptible annotation - that's saying that this code is safe to use within the GC itself. Notice how the file doesn't contain even a single 'new! (Outside of PosixVirtualMemoryProviderFeature, which is something else.)
You are writing a GC in Java, yes but have access to low-level memory abstractions/interfaces, right?
Whereas I was initially wondering how to write a GC in "pure Java" that doesn't have access to low-level memory interfaces.
Does it make sense why I was asking, now? Or am I still not getting it?
To be clear, Java the language is Java, I'm not going to argue that it's not Java because of special primitives / interfaces available to write the GC here, but it is not what most people would think of when considering the limitations of the runtime everyone's using.
I think I'd phrase it like this: you can write a GC mostly in Java.
Other GCs than the default Java one in native image like G1 actually embed the C++ version of the implementation instead of writing it in Java.
Yeah, but also the code shown above used native low level primitives like mmap which typically aren't available.
AOT, special behavior directives (@Uninterruptible), native memory access, making sure not to use new (?), at that point you are formally using Java, the language, but it's sort of its own thing.
So, that's still cool and likely no way around it but I wonder to what degree it's actually beneficial: Your program is much closer to a C++ program than a Java one except for syntax and the additional glue abstractions that typically exist in neither. In a (exaggerated) sense it's like it's written in a C++ DSL embedded in Java.
If you know how to write C++ it's possibly simpler to just write it in C++ as you know how memory management there works. If you know Java you need to get familiar to the extensions used here.
This is a bit different from the idea of self-hosting a compiler for instance where you can start writing your compiler now ideomatically in your own language instead of something different. For instance if your language & runtime has GC it's much simpler / safer to write a program in it, and so a compiler in it than pre-self-hosting (if the earlier compiler was written in C).
So what in particular is afforded by writing the GC in "Special Java" ? Is it just about being able to say "it's all in Java" or are there language features in "Special Java" that make live easier than C++? Or other benefits? For instance, I imagine use of the wider ecosystem / libraries isn't possible whereas in C++ it is (more so at least).
It would be nice if somehow you could write a GC itself in regular old Java without having to worry about aspects of how to do it in a special, restricted way. Say, the code you write and which runs the garbage collection creates objects, which subsequently get cleaned up by your very own GC program.
In the end you still have to work with low level abstractions / memory though and maybe that's still different to the self-hosted compiler example in a sense: There you translate code into a language that is more low level but you don't need to have these abstractions available in your own language / on your stage of computation / while running your compiler.
Native calls are a normal part of Java. And the pointer and word classes used could be implemented using the Unsafe class which is present in Java.
the gist is you treat memory as a big array, then write a program to manipulate that array. it's really just a decision about what you want to "take as primitive" in your implementation. could be brk, could be malloc and free, or something higher level.
My turn: NASDAQ moved from cpp to Java quite a few years ago. Do you think you know something they don't?
SweetHome 3D IS slower than competitive projects written in C++.
C++ tools tend to be faster than comparative Java tools because of fast startup time, no GC, and being the default choice for performance sensitive projects for decades.
C++ is definitively faster because of inherent advantages.
You appear to be jumping to the third based on the first which appears erroneous in argument even if you turned out to be correct. In actuality it appears that for most things in the same ballpark language choice isn't necessarily the only or even the most important factor. This is even more true for things where startup time is an inconsequential factor, with better GC that doesn't result in lengthy pauses, and where development time is a substantial limiting factor wherein being quicker to work with may result in more time available to improve other design choices yielding as good or better results.