Closed yissatayev closed 3 years ago
You need to call AttachCurrentThread on the *JVM
. This returns a new *Env
which can used in the current thread. And then call DetachCurrentThread when your done.
One way to do this so you don't have keep attaching threads is something like:
var funcChan = make(chan func(*jnigi.Env))
func RunOnJavaAttachedThread(f func(*jnigi.Env)) {
funcChan <- f
}
// run with go keyword from main
func RunJavaThreadFuncs(jvm *jnigi.JVM) {
env := jvm.AttachCurrentThread()
for f := range funcChan {
f(env)
}
}
/*
In end-point handler
RunOnJavaAttachedThread(func(env *jnigi.Env) {
// run my java code here
})
*/
This means that bits of Java code will be only run one at a time. You could use sync.Pool if you want to handle more than one at a time.
One thing to note is AttachCurrentThread
calls runtime.LockOSThread. I might change this in the future so that the program it self calls this.
Any update on this? Hope this helped. Probably best to close this if this is no longer a problem.
Sorry for the late reply, I missed your first reply somehow. I just tried the suggested solution and getting FATAL ERROR in native method: Using JNIEnv in the wrong thread. Probably I am doing something wrong. Let me look into this a bit more and I'll come back to you. Thank you.
Hi @timob I was able to implement the approach you suggested. Everything works, but sometimes I receive the following warning messages:
WARNING: JNI local refs: 33, exceeds capacity: 32
After some more requests:
WARNING: JNI local refs: 66, exceeds capacity: 65
And this continues incrementing. Is that OK? Or is it potentially a problem?
See EnsureLocalCapacity in JNI docs. Generally it's not problem, but if it's a long running service, you probably want to use DeleteLocalRef
or Push/PopLocalFrame
to free references to Java objects when you are done with them.
Good to hear that code fixed the problem in the issue title 👍👍👍. Please open another issue if you're having a different problem too.
Hi,
If I initialize JVM (load, create, etc.) in the main function, I can successfully execute a Java code without any problems. However, If I try to initialize JVM only once after the application has started instead of initializing for each call and call a Java code in handler functions, I get the following error:
Could you please help with what I am trying to achieve? Basically, I want to create an end-point in a Go application which will call some Java code each time request is received.
The sample code I am working with is here TinkJNIGo