Live data from Hacker News

I have written a JVM in Rust

andreabergia.com

71–80 of 185 posts

Re: I have written a JVM in Rust

#71

I have a few questions about the garbage collection. One of the hard parts of implementing a garbage collector is making sure everything is properly rooted (especially with a moving collector). you have the `do_garbage_collection` method marked unsafe[1], but don't explain what the calling code needs to do to ensure it is safe to call. How do you ensure all references to the heap are rooted? This is not a trivial pro…

It's pretty straightforward. Their VM maintains its own notion of a callstack instead of using the native callstack. That lets them iterate over it and find all of the parameters and locals on the VM's callstack and use them as roots. There is a performance cost for a VM having its own virtual callstacks like this, but it makes GC tracing much simpler. (It also makes implementing interesting concurrency and control f…

Seems like that would take care of roots for the bytecode's themselves, but not for "native" functions[1]. Allocating a new object could call gc[2], and native functions are using the native callstack. It seems like it would be easy to allocate in a native function and any unrooted references would be invalidated. In fact I see a case like that here[3]. That method creates a reference with `expect_concrete_object_at` and then calls gc with `new_java_lang_class_object`. It avoids UB by not using `arg` after the call that gc's, but there is nothing stopping you from using `arg` again (and having an invalid reference).

[1] https://github.com/andreabergia/rjvm/blob/main/vm/src/native...

[2] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...

[3] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...

Re: I have written a JVM in Rust

#72
post #70
post #7

See also https://jacobin.org/ for JVM 17 written in Go.

That is a very interesting name for a programming project lol. The Jacobins were a revolutionary political club during the French Revolution in the 1790's. It's also the name of a magazine at https://jacobin.com

It's starts with the letters "ja", that's all that matters for a Java-related project.

Re: I have written a JVM in Rust

#73
post #48
post #39

Missed opportunity to call it Just

Just is already 'taken' in the Rust community as it is a command runner utility like make: https://github.com/casey/just

Ooh, I like that. `just build` feels like a good plea to make to the Rust compiler lol

Re: I have written a JVM in Rust

#74
post #61
post #58

Earlier quoted context omitted.

Right, just because something is a "toy" doesn't mean it's not still impressive. If someone implemented a "toy" database that could parse and execute SQL queries, distribute data across nodes, etc., you would probably not want to use that in production, but it's still a very impressive project for a single person to pull off, even if it's riddled with bugs. Getting a very complex system to "just barely functional" is…

Being impressing or otherwise is very subjective. SQL (ACID) over multiple non-cache-coherent nodes is extremely difficult to pull with regards to consistency, though.

> SQL (ACID) over multiple non-cache-coherent nodes is extremely difficult to pull with regards to consistency, though.

Thats... why it's a toy! I'm really not sure what you're missing here.

Re: I have written a JVM in Rust

#75
This project is like the ground floor of the JVM, not the whole tower. I like though how the project's page is direct and clear about that.

A lot of the foundation and ground-floor mechanics are pretty interesting though.

Re: I have written a JVM in Rust

#76

I am curious if your ran into limitations due to the lifetimes on this signature fn execute_instruction( &mut self, vm: &mut Vm , call_stack: &mut CallStack , instruction: Instruction, ) -> Result , MethodCallFailed > When I try to add a lifetime to the `Err` variant of a `Result` and that lifetime is invariant (which it is due to `vm` and `call_stack`) it usually means that I can't use the question mark operator or…

EDIT: Looks like this is not an issue because the invariant lifetime 'a is not used for the mutable reference of vm or call_stack. So it's not the invariance that is the problem, but rather how Rust reasons about the lifetime of mutable references, which this avoids.

In that case I don't understand what the point of 'a is on VM and CallStack. You can create[1][2] those with any unbounded lifetime (including 'static[3]), which means it is not constraining anything. What is the lifetime 'a doing here? Why not remove it?

[1] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...

[2] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...

[3] https://github.com/andreabergia/rjvm/blob/be9c54066c64a82879...

Re: I have written a JVM in Rust

#77

Earlier quoted context omitted.

It's pretty straightforward. Their VM maintains its own notion of a callstack instead of using the native callstack. That lets them iterate over it and find all of the parameters and locals on the VM's callstack and use them as roots. There is a performance cost for a VM having its own virtual callstacks like this, but it makes GC tracing much simpler. (It also makes implementing interesting concurrency and control f…

Seems like that would take care of roots for the bytecode's themselves, but not for "native" functions[1]. Allocating a new object could call gc[2], and native functions are using the native callstack. It seems like it would be easy to allocate in a native function and any unrooted references would be invalidated. In fact I see a case like that here[3]. That method creates a reference with `expect_concrete_object_at`…

Indeed you are right, this is definitely a bug and could cause errors.

I guess the solution would be to add an explicit API to create a GC root, invoked by native methods (which is a bit complicated by the fact that I use a moving collector).

Many years ago I was using SpiderMonkey in a c++ project and I seem to remember there were some APIs for native callbacks to invoke that rooted values. Same problem and similar solution. :-)

Re: I have written a JVM in Rust

#78
That is pretty awesome! When I joined the Java effort in '92 (called Oak at the time) the group I was with was looking at writing a full OS in Java. The idea being that you could get to just the minimal set of things needed as "machine code" (aka native methods) you could reduce the attack surface of an embedded OS. (originally Java was targeted to run in things like TV's and other appliances). We were, of course, working in C rather than Rust for the native methods. The JVM in Rust though adds a solid level of memory safety to the entire process.

Re: I have written a JVM in Rust

#79

Earlier quoted context omitted.

Seems like that would take care of roots for the bytecode's themselves, but not for "native" functions[1]. Allocating a new object could call gc[2], and native functions are using the native callstack. It seems like it would be easy to allocate in a native function and any unrooted references would be invalidated. In fact I see a case like that here[3]. That method creates a reference with `expect_concrete_object_at`…

Indeed you are right, this is definitely a bug and could cause errors. I guess the solution would be to add an explicit API to create a GC root, invoked by native methods (which is a bit complicated by the fact that I use a moving collector). Many years ago I was using SpiderMonkey in a c++ project and I seem to remember there were some APIs for native callbacks to invoke that rooted values. Same problem and similar…

> I guess the solution would be to add an explicit API to create a GC root, invoked by native methods (which is a bit complicated by the fact that I use a moving collector).

This is why I do in the Wren VM. Any time a native C function has the only reference to a GC-managed object and it's possible for a collection to occur, it calls a function to temporarily add the object to a list of known roots.

Re: I have written a JVM in Rust

#80

That is pretty awesome! When I joined the Java effort in '92 (called Oak at the time) the group I was with was looking at writing a full OS in Java. The idea being that you could get to just the minimal set of things needed as "machine code" (aka native methods) you could reduce the attack surface of an embedded OS. (originally Java was targeted to run in things like TV's and other appliances). We were, of course, wo…

> writing a full OS in Java

IMAO, Android kind of achieve that...kind of. They write lots of OS logics in Java (or Kotlin) but mixing lots of system services written in native code at the same time, interconnected by the famous (or infamous?) Bind IPC.

Post reply on HN