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/....
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.