Exception 0xC0000005 from JNI_CreateJavaVM (jvm.dll)
JVM actively uses OS signals (or exceptions in Windows terminology) for its own purposes:
- for implicit null pointer checks and stack overflow checks;
- for safepoint polling;
- for remote memory barriers;
- etc.
SEGV (or exception 0xC0000005) is also generated intentionally on JVM startup to verify certain CPU/OS features. Some OSes or hypervisors had a bug that AVX registers are not restored after signal processing. Therefore, JVM needs to check whether this is the case (the source). So it generates an exception by writing to zero address and then handles it.
This is what happens in your case. And yes, it is normal.
Exception 0xC0000005 in jvm.dll when creating an instance via JNI NewObject
After days, I figured it out.
The constructor I am invoking expects a parameter. The type is long
(Java) aka J
(JNI Type Signature) aka jlong
(corresponing C type). A C uintptr_t
is compatible with a jlong
.
On Linux, my uintptr_t
is 8 bytes long, since I am in a amd64 environment with 64 bit applications. For Windows, the application was build in 32 bit. As a result uintptr_t
is only 4 bytes long, but the JVM still expect a 8 byte jlong
. However, NewObject
is a variadic function, automatic promotion does not happen and type safety is not guaranteed.
login(uintptr_t connection, const char* username, …) {
…
jmethodID constructor = (*env)->GetMethodID(env, ps->class, "<init>", "(JLjava/lang/String;)V");
jstring jusername = (*env)->NewStringUTF(env, username);
jlong jconnection = connection;
jobject instance = (*env)->NewObject(env, ps->class, constructor, jconnection, jusername);
A simple cast to the correct type was the solution. I expect this pitfall to exist with CallVoidMethod
or any of the Call*Method
mentioned in the documentation, too.
Unable to use JNI when enabled from within Win32/MFC application
In the end, I figured this out. Apparently the JNI throws exceptions on startup by design to verify the environment it's running in. See Exception 0xC0000005 from JNI_CreateJavaVM (jvm.dll).
When I disabled the particular exception in Win32 exceptions in visual studio , it all works fine.
JNI_CreateJavaVM crash my program without any message or exception
Now I have turn to Load jvm.dll dynamicly:
typedef jint(JNICALL *pCreateJavaVM)(JavaVM **, void**, void *);
HINSTANCE hInstance = LoadLibrary(L"C:\\Program Files (x86)\\Java\\jre1.8.0_25\\bin\\client\\jvm.dll");
pCreateJavaVM CreateJavaVM = (pCreateJavaVM)GetProcAddress(hInstance, "JNI_CreateJavaVM");
options[0].optionString = "-Djava.class.path=.";
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
status = CreateJavaVM(&jvm, (void**)&env, &vm_args);
And it works...I do not know why...
JNI_CreateJavaVM function method does not work and cannot be debugged
Classpath
There is a space between key and equal sign. The space must be removed.
char optionString[] = "-Djava.class.path =D:/Program Files/Java/jdk1.8.0_191/lib/";
Classpath value
The java.class.path value must point to the base directory where your compiled .class files are located.
It looks like you're not using a package name, then it's the directory where Main.class is located, so probably it should look something like this:
char optionString[] = "-Djava.class.path=c:/Users/name/MyJavaPrograms/classes";
Access violation
SEGV (or exception 0xC0000005) is also generated intentionally on JVM startup to verify certain CPU/OS features.
see this fine answer: https://stackoverflow.com/a/36258856
In Visual Studio, when the exception dialog is shown, simply turn off that it breaks there. This will prevent you from seeing it again the next time you start the program again.
Java
Just for the sake of completeness: the Java method should look like this:
public class Main {
public static void test(int num) {
System.out.println("Java: test called with '" + num + "'");
}
...
Visual Studio Configuration
The jvm.dll needs to be found. In Visual Studio under Configuration Properties/Debugging/Environment add PATH=%PATH%;<path-to-jdk>\bin\server
For later deployment you could think about putting the whole JRE into a subfolder of your application and reference it with a relative path.
Demo
Finally a brief demo (added a \n here printf("result=%d\n", res);
to have a separate line):
0xC0000005: Access violation reading location 0x0000000000000000
You need to set options.extraInfo = 0;
I would do all of this for good measure. Defensive programming demands that everything is initialized.
#define CLEAR(x) memset(&x, 0, sizeof(x))
JavaVM *jvm(0);
JNIEnv *env(0);
JavaVMInitArgs vm_args;
CLEAR(vm_args);
JavaVMOption options;
CLEAR(options);
Note:
typedef struct JavaVMOption {
char *optionString;
void *extraInfo;
} JavaVMOption;
EDIT: None of this turned out to be the problem. The solution is in the comments -- the JVM is throwing access violation exceptions. They are caught and handled, but not before Visual Studio leads you to believe there is a problem.
Related Topics
How to Ignore Certain Elements When Comparing Xml
How to Check a Timeperiod Is Overlapping Another Time Period in Java
Accessing a File Inside a .Jar File
Scanner Class Skips Over Whitespace
Does Variable = Null Set It for Garbage Collection
Cannot Rerun Java JPAckage Installer If Already Installed, Second Time Just Exits Without Warning
Why Is "Out of Range" Not Thrown for 'Substring(Startindex, Endindex)'
How to Invert the Case of a String in Java
How Can "This" of the Outer Class Be Accessed from an Inner Class
Printf %F with Only 2 Numbers After the Decimal Point
Why Can't You Reduce the Visibility of a Method in a Java Subclass
Run Java File as Administrator with Full Privileges
No Idea Annotations Attached to the Jdk 1.8 (C:\...), Some Issues Will Not Be Found
Any Simple Way to Explain Why I Cannot Do List<Animal> Animals = New Arraylist<Dog>()
Maximum Size of a Method in Java 7 and 8
Getting Java.Lang.Reflect.Invocationtargetexception While Adding a Button to Layout
How to Insert a Row Between Two Rows in an Existing Excel with Hssf (Apache Poi)