Skip to content
This repository has been archived by the owner on May 10, 2019. It is now read-only.

Multi-thread use case #19

Open
hongxuchen opened this issue Nov 14, 2017 · 6 comments
Open

Multi-thread use case #19

hongxuchen opened this issue Nov 14, 2017 · 6 comments

Comments

@hongxuchen
Copy link

My code is in a multi-thread setting, inside each thread, there is a need to call jvm functions.

I find that the "jvm" instance itself cannot be constructed separately inside each thread, by loading the classpath with proper options. In this case, it will panic with a message:

 '`JNI_CreateJavaVM()` signaled an error: JVM exists already'` ...rucaja-0.4.0/src/jvm.rs:186:12

This alternative seems to be putting JVM construction code before spawning threads and then passing as parameters.

The problem is that I'm not quite sure whether this will cause data race internally at the JVM side.

Since I know little about JNI and would like to be merely a "user" of rucaja, Could you please advise?

@kud1ing
Copy link
Owner

kud1ing commented Nov 14, 2017

My impression is that one can only have exactly one JVM in one process in total, and not sequentially: https://docs.rs/rucaja/0.4.2/rucaja/struct.Jvm.html#method.new

If i understand correctly, sharing the same JVM from different Rust threads should be safe, since we attach/detach using JvmAttachment (AttachCurrentThread() + DetachCurrentThread()). There still could be bugs, since i haven't tried what you are doing.

An alternative could be to use different Rust processes.

@kud1ing
Copy link
Owner

kud1ing commented Nov 14, 2017

And thanks by the way for using Rucaja. I am interested in making it more usable, so your feedback is very appreciated.

@kud1ing
Copy link
Owner

kud1ing commented Nov 14, 2017

I have no deep JNI knowledge myself. @fpoli, @treyzania, @tupshin, @Dushistov do you have any experience regarding multithreading and JNI? Is the above approach sufficient?

@fpoli
Copy link
Contributor

fpoli commented Nov 15, 2017

I'm also not an expert, but I just found that "according to docs, only one thread can use use JVM at a time". So, it should be possible by using a Mutex<Jvm> (or some other technique).

@hongxuchen
Copy link
Author

@kud1ing and @fpoli Thanks so much for your help! I think I've to choose another approach.

@treyzania
Copy link
Contributor

treyzania commented Nov 21, 2017

@kud1ing I'm a bit late to this party, but I would assume that we could restructure the APIs a bit so that we always return a Mutex<Jvm> or some preferably opaque type that makes sure that only one thread is actually interacting with the JVM at a time. This would allow us to automagically issue the call to DetachCurrentThread in the Drop implementation for whatever this type returns when we try to "attach" to the JVM, which would be super awesome!

Unless we want to make Jvm be !Send, which would fix the problem, but in a very shitty way. As I side note, I can't figure out why anybody would need !Send outside of wrapping code written in other languages (OpenGL contexts are per-thread, etc.) or maybe in a kernel.

EDIT: I'm now realizing that Jvm is naturally !Send because of how Rust auto-derives things. I'd need to think on it a bit as I am far from a JNI expert. Worst-case scenario if we can't find a reliable way to pass it between threads somehow would be to have a "JNI thread" that actually owns the JVM, that we can pass a closure to be queued to be executed (with std::sync::mspc or something like it), and then layer some abstractions on top of that to make it easy to simple things with. This is so suboptimal, but it's a worse-case scenario, honestly. The fact that the JVM can spawn its own threads that can potentially have references to things that we allocated makes things all kinds of complicated. So those are more concerns (perhaps translating using Box::into_raw and Box::from_raw?) for dealing with passing things into the JVM.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants