I have created a JNI wrapper with swig for a library. I use swig directors to call back into the JVM. Some of these callbacks occur on threads created within the native library. The first callback on a non JVM thread fails with a SIGSEGV which I could trace down to ignoring the negative return value (-1) of AttachCurrentThread and thus dereferencing a jenv pointer which is actually null. This happens in the swig generated code.
I have tried to call back into the JVM via the director classes from a thread that I created on the native side. This works fine. It does however not work from the thread created by the library I wrapped.
What can be possible reasons that AttachCurrentThread fails?
When a thread does not have sufficient stack space left AttachCurrentThread fails. Unfortunately the documentation of the Oracle JVM does not mention the minimum required stack space for AttachCurrentThread to work.
In my case the native library was optimized for embedded hardware and therefore creates threads generally with a stack size of 100000 bytes.
Related
I'm running a shared library (compiled with Intel) using JNA. In rare cases the Fortran-call ends with a forrtl : severe code. Something like
forrtl: severe (408): fort: (3): Subscript #1 of the array IWU has value 0 which is less than the lower bound of 1
Is there a way to "catch" this runtime error using JNA?
There is no general mechanism for passing error codes from native code to JNA. At best, JNA will know the function failed from its return value.
However, if the native code provides a means of reading those error codes (e.g., the Windows GetLastError() function, or the global errno variable on Linux and macOS), then more specific details can be retrieved.
For an Intel Fortran "severe" error, program execution stops unless it's handled on the native side, so I don't think there's anything you can do to "catch" it in JNA unless it's already "caught" in the library you're using... in which case, you just need to properly react to the failed method call. The Fortran source can be modified to catch some runtime errors (such as in I/O, dynamic memory management or image control) and return this status. However, for this particular array bounds error of the question, this may not apply.
Hypothetical: Calling C++ code from Java is relatively straightforward. As I understand it, the C++ code is executed in the same thread as the Java code calling it (correct me if I'm wrong). If the C++ code then starts a new native thread with pthread_key_create(), can this thread call back into Java through JNI? If so, how is this possible, since the code would then be executing in a pthread instead of a Java thread on the JVM?
As I understand it, the C++ code is executed in the same thread as the Java code calling it (correct me if I'm wrong)
The JNIEnv is attached to a thread, you cannot share a JNIEnv between threads. Your native functions all receive a JNIEnv as the first argument so it corresponds to the current Thread's JNIEnv.
If the C++ code then starts a new native thread with pthread_key_create(), can this thread call back into Java through JNI?
All threads are Linux threads, scheduled by the kernel. They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then attached to the JavaVM. For example, a thread started with pthread_create can be attached with the JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv, and cannot make JNI calls.
If so, how is this possible, since the code would then be executing in a pthread instead of a Java thread on the JVM?
See previous response too ;) (the first two sentences)
More infos here and here.
In order to make upcalls to Java, a natively create thread should call first AttachCurrentThread or AttachCurrentThreadAsDaemon.
Take a look at this sample:
In this sample, you have a multi thread based code that calls Java code.
You can find full description here: http://jnicookbook.owsiak.org/recipe-no-027/
And source code is available here:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo027
I will not put all the codes here as it takes some space.
In fact, here: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo032,
you have more suitable sample for your. Where JVM calls C that calls JVM back invoking static method in Main class.
> java -Djava.library.path=${LD_LIBRARY_PATH}:./lib -cp target recipeNo032.Main
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM
I will call JVM
From JVM
Have fun with JNI.
Java byte code is interpreted however this is not as fast as directly executing native code on the JVM’s host CPU. To improve performance the Oracle Hotspot VM looks for “hot” areas of byte code that are executed regularly and compiles these to native code. The native code is then stored in the code cache in non-heap memory. In this way the Hotspot VM tries to choose the most appropriate way to trade-off the extra time it takes to compile code verses the extra time it take to execute interpreted code.
Not all JVMs support native methods, however, those that do typically create a per thread native method stack. If a JVM has been implemented using a C-linkage model for Java Native Invocation (JNI) then the native stack will be a C stack. In this case the order of arguments and return value will be identical in the native stack to typical C program. A native method can typically (depending on the JVM implementation) call back into the JVM and invoke a Java method. Such a native to Java invocation will occur on the stack (normal Java stack); the thread will leave the native stack and create a new frame on the stack (normal Java stack).
What does it mean native as for Code cache and native stack? When I write a program on Ubuntu and run it on Eclipse, and the program runs endlesly a loop in which there is some code, will this code go to code cache? Will it be recompiled to some native language and which, when I am using Ubuntu, Oracle Java 1.7, I have Intel i5 processor.
The same question about Oracle JVM7 - is it written in C? When native stack would be used and what exactly mean native in this case, when I have Ubuntu and Oracle Java 1.7 ?
As far as I understand JVM creates a separate stack for native methods bind to Java code via JNI. It has been done so because those methods has their own stack specifications. But it all depends on JVM implementation, it also could be that there is no separate stack for Native methods.
You can take a look at this article:
http://www.artima.com/insidejvm/ed2/jvm9.html
I'm using a library that calls the JNI_CreateJavaVM function inside the library code. However, I also need some JNI Wrappings and I need to call the same function JNI_CreateJavaVM to get the JNIEnv* to my application.
But the second call is failing.
is there any way to do this?
The library does not support getting or setting the JNIEnv* created inside the library.
You cannot create more than one JVM from the same process:
As of JDK/JRE 1.2 , creation of multiple VMs in a single process is not supported.
You may be able to attach your current thread to the existing JVM though using AttachCurrentThread function. See the docs for the Invocation API. The equivalent document in Java 15 simply states:
Creation of multiple VMs in a single process is not supported.
You will need a pointer to the JavaVM object. See if JNI_GetCreatedJavaVMs() can help you, I'm not sure if this is per-process (in which case it will only ever be a single element list) or per machine. In either case the JavaVM will have to be the one that the library is using or you probably will not be doing what you want. If you can access that then you should be able to make invocations on other objects in your Java application, but make sure that it is thread-safe.
I'm browsing through OpenJDK sources and cannot find the place where optimized code is replaced.
I wonder how this can be done in protected mode, isn't it some kind of selfmodifing code which should be prevented by the OS?
The "JITer" allocates space in say the heap or stack and inserts assembly code into it. No, self modifying code is perfectly fine. VirtualProtect (Windows) and mmap (Unix) can map pages as executable. General purpose operating systems by default will mark executable pages as read/execute but not write, you can still typically change this at runtime.
If there was no way to modify code, there would be no way to load a dll unless it's loaded to a fixed Virutal Address and shared into each process's address space; then you'd get address space hell instead of dll hell.
I'm guessing you heard of the NX bit or DEP etc, those just protect you from executing non-executable code, which helps a bit against stack overflows and the likes.
The JIT code doesn't replace optimized machine code; it replaces loaded Java bytecode. I don't know how this is implemented in OpenJDK, but typically, the JVM loads the byte code and keeps it in some form of internal structure, usually in a class that has a virtual function or virtual functions for executing the code. When it is just-in-time compiled, the pointer to that internal structure is replaced by a pointer to a class with the same interface, where the underlying representation is native machine code instead of Java byte code, and the virtual methods are implemented such that they invoke the native code rather than interpreting the byte code. There is no modification of code, merely pointing to different places.