I have an C application that runs Java through JNI. The Java application starts, does some stuff and after a second or two I get either SIGSEGV or SIGBUS . There is no java crash dump file.
Here is where it crashes:
libjvm.dylib`jni_CallStaticVoidMethod:
0x104ad1653 <+0>: pushq %rbp
0x104ad1654 <+1>: movq %rsp, %rbp
0x104ad1657 <+4>: pushq %r15
0x104ad1659 <+6>: pushq %r14
0x104ad165b <+8>: pushq %r12
0x104ad165d <+10>: pushq %rbx
0x104ad165e <+11>: subq $0x150, %rsp
0x104ad1665 <+18>: movq %rdx, %rbx
0x104ad1668 <+21>: movq %rsi, %r14
0x104ad166b <+24>: movq %rdi, %r15
0x104ad166e <+27>: testb %al, %al
0x104ad1670 <+29>: je 0x104ad16aa ; <+87>
0x104ad1672 <+31>: movaps %xmm0, -0x140(%rbp)
0x104ad1679 <+38>: movaps %xmm1, -0x130(%rbp)
0x104ad1680 <+45>: movaps %xmm2, -0x120(%rbp)
0x104ad1687 <+52>: movaps %xmm3, -0x110(%rbp)
0x104ad168e <+59>: movaps %xmm4, -0x100(%rbp)
0x104ad1695 <+66>: movaps %xmm5, -0xf0(%rbp)
0x104ad169c <+73>: movaps %xmm6, -0xe0(%rbp)
0x104ad16a3 <+80>: movaps %xmm7, -0xd0(%rbp)
0x104ad16aa <+87>: movq %r9, -0x148(%rbp)
0x104ad16b1 <+94>: movq %r8, -0x150(%rbp)
0x104ad16b8 <+101>: movq %rcx, -0x158(%rbp)
0x104ad16bf <+108>: movq %r15, %rdi
0x104ad16c2 <+111>: callq 0x104c8c550 ; JavaThread::thread_from_jni_environment(JNIEnv_*)
0x104ad16c7 <+116>: movq %rax, %r12
0x104ad16ca <+119>: movq %r12, -0x28(%rbp)
0x104ad16ce <+123>: leaq -0x28(%rbp), %rdi
0x104ad16d2 <+127>: movl $0x6, %esi
0x104ad16d7 <+132>: callq 0x104926aac ; ThreadStateTransition::trans_from_native(JavaThreadState)
0x104ad16dc <+137>: movq %r12, -0x30(%rbp)
0x104ad16e0 <+141>: movq %r12, -0x50(%rbp)
0x104ad16e4 <+145>: movq $0x0, -0x48(%rbp)
0x104ad16ec <+153>: cmpq $0x0, 0x8(%r12)
0x104ad16f2 <+159>: je 0x104ad16fd ; <+170>
0x104ad16f4 <+161>: leaq -0x50(%rbp), %rdi
0x104ad16f8 <+165>: callq 0x104c5cf7c ; WeakPreserveExceptionMark::preserve()
0x104ad16fd <+170>: movq %r14, %rsi
0x104ad1700 <+173>: movq %r15, %rdi
0x104ad1703 <+176>: movq %rbx, %rdx
0x104ad1706 <+179>: nop
0x104ad1707 <+180>: nopl (%rax)
0x104ad170b <+184>: leaq -0x170(%rbp), %rax
0x104ad1712 <+191>: movq %rax, -0x58(%rbp)
0x104ad1716 <+195>: leaq 0x10(%rbp), %rax
0x104ad171a <+199>: movq %rax, -0x60(%rbp)
0x104ad171e <+203>: movl $0x30, -0x64(%rbp)
0x104ad1725 <+210>: movl $0x18, -0x68(%rbp)
0x104ad172c <+217>: movl $0xe, -0x78(%rbp)
0x104ad1733 <+224>: movq (%rbx), %rax
0x104ad1736 <+227>: movq 0x8(%rax), %rax
0x104ad173a <+231>: movzwl 0x22(%rax), %ecx
0x104ad173e <+235>: movq 0x8(%rax), %rax
0x104ad1742 <+239>: movq 0x50(%rax,%rcx,8), %rsi
0x104ad1747 <+244>: leaq -0xb8(%rbp), %r14
0x104ad174e <+251>: movq %r14, %rdi
0x104ad1751 <+254>: callq 0x104ca2c14 ; SignatureIterator::SignatureIterator(Symbol*)
0x104ad1756 <+259>: movl $0x63, -0xa0(%rbp)
0x104ad1760 <+269>: movq $0x0, -0x98(%rbp)
0x104ad176b <+280>: leaq 0x4f827e(%rip), %rax ; vtable for JNI_ArgumentPusherVaArg
0x104ad1772 <+287>: addq $0x10, %rax
0x104ad1776 <+291>: movq %rax, -0xb8(%rbp)
0x104ad177d <+298>: movq -0x58(%rbp), %rax
0x104ad1781 <+302>: movq %rax, -0x80(%rbp)
0x104ad1785 <+306>: movq -0x68(%rbp), %rax
0x104ad1789 <+310>: movq -0x60(%rbp), %rcx
0x104ad178d <+314>: movq %rcx, -0x88(%rbp)
0x104ad1794 <+321>: movq %rax, -0x90(%rbp)
0x104ad179b <+328>: leaq -0x78(%rbp), %rsi
0x104ad179f <+332>: movq %r15, %rdi
0x104ad17a2 <+335>: movq %rbx, %rdx
0x104ad17a5 <+338>: movq %r14, %rcx
0x104ad17a8 <+341>: movq %r12, %r8
0x104ad17ab <+344>: callq 0x104ad8877 ; jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)
0x104ad17b0 <+349>: cmpq $0x0, 0x8(%r12)
0x104ad17b6 <+355>: jne 0x104ad17bf ; <+364>
0x104ad17b8 <+357>: nop
0x104ad17b9 <+358>: nopl (%rax)
0x104ad17bd <+362>: jmp 0x104ad17c4 ; <+369>
0x104ad17bf <+364>: nop
0x104ad17c0 <+365>: nopl (%rax)
0x104ad17c4 <+369>: cmpq $0x0, -0x48(%rbp)
0x104ad17c9 <+374>: je 0x104ad17d4 ; <+385>
0x104ad17cb <+376>: leaq -0x50(%rbp), %rdi
0x104ad17cf <+380>: callq 0x104c5cefa ; WeakPreserveExceptionMark::restore()
0x104ad17d4 <+385>: leaq -0x30(%rbp), %rdi
0x104ad17d8 <+389>: callq 0x1048ffc80 ; HandleMarkCleaner::~HandleMarkCleaner()
0x104ad17dd <+394>: leaq -0x28(%rbp), %rdi
0x104ad17e1 <+398>: movl $0x6, %esi
0x104ad17e6 <+403>: movl $0x4, %edx
0x104ad17eb <+408>: callq 0x104931e04 ; ThreadStateTransition::trans_and_fence(JavaThreadState, JavaThreadState)
0x104ad17f0 <+413>: addq $0x150, %rsp
0x104ad17f7 <+420>: popq %rbx
0x104ad17f8 <+421>: popq %r12
0x104ad17fa <+423>: popq %r14
0x104ad17fc <+425>: popq %r15
0x104ad17fe <+427>: popq %rbp
0x104ad17ff <+428>: retq
The debuger points to the line (in the code above):
0x104ad17b0 <+349>: cmpq $0x0, 0x8(%r12)
and next points to the first line of this code as the cause (it does not say where is this code from):
-> 0x1058e5535: movl 0xc(%rdx), %r10d
0x1058e5539: movl 0xc(%r12,%r10,8), %ebx
0x1058e553e: movl 0x10(%rsi), %r8d
0x1058e5542: movl 0xc(%r12,%r8,8), %r9d
0x1058e5547: movl %r9d, 0x14(%rsp)
0x1058e554c: movl 0xc(%rsi), %r11d
0x1058e5550: movl %ebx, %ebp
0x1058e5552: addl %r11d, %ebp
As I say, this does not happen immediately - the Java application manages to do a couple things. The crash apparently occurs when I tries to use AWT gui classes. Also, the log shows this line (not sure if this is related):
WARNING: GL pipe is running in software mode (Renderer ID=0x1020400)
Is this a JVM bug? How should I proceed?
EDIT:
The relevant source code:
void* runJava(void* arg) {
JNIEnv *env;
JavaVM * jvm;
int nOptions = 1;
char jvmLibPath[PATH_MAX];
if (! jreSearch(jvmLibPath)) {
return NULL;
}
void* handle = dlopen(jvmLibPath, RTLD_LAZY);
NSLog(@"loaded jvm library %s\n", jvmLibPath);
if (handle == NULL) {
NSLog(@"error: %s\n", dlerror());
exit(EXIT_FAILURE);
}
PtrCreateJavaVM ptrCreateJavaVM = (PtrCreateJavaVM) dlsym(handle, "JNI_CreateJavaVM");
if (ptrCreateJavaVM == NULL) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
JavaVMOption* options = (JavaVMOption*) malloc(sizeof(JavaVMOption) * (nOptions));
options[0].optionString = "-Djava.class.path=../MyJavaApp.jar";
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = nOptions;
vm_args.options = options;
vm_args.ignoreUnrecognized = 0;
int ret = ptrCreateJavaVM(&jvm, (void**) &env, &vm_args);
if (ret < 0)
NSLog(@"\nUnable to Launch JVM\n");
if (env == NULL) {
exit(EXIT_FAILURE);
}
jclass mainClass = (*env)->FindClass(env, "mainpackage.MyMainClass");
if (mainClass == 0) {
NSLog(@"Failed to find class (or it's dependencies)");
}
jmethodID mainMethod = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V");
if (mainMethod == 0) {
NSLog(@"Failed to acquire main() method of main class\n");
exit(EXIT_FAILURE);
}
NSArray *args = [[NSProcessInfo processInfo] arguments];
int argc_ =(int)[args count];
char** argv_ = getArray(args);
//application name is not passed to java app, hence (argc - 1)
jobjectArray appArgs = (*env)->NewObjectArray(env, argc_ - 1,(*env)->FindClass(env, "java/lang/String"), NULL);
int i;
for (i = 0; i < argc_ - 1; i = i + 1) {
//argv[i + 1] skipps application name
jstring arg = (*env)->NewStringUTF(env, argv_[i + 1]);
(*env)->SetObjectArrayElement(env, appArgs, i, arg);
}
NSLog(@"calling main method\n");
(*env)->CallStaticVoidMethod(env, mainClass, mainMethod, appArgs);
NSLog(@"after main method\n");
(*jvm)->DestroyJavaVM(jvm);
if (options != NULL) {
int i;
for (i = 0; i < nOptions; i++) {
free(options[i].optionString);
}
}
NSLog(@"JVM destroyed\n");
freeArray(argv_);
pthread_mutex_lock(&javaFinishedMutex);
pthread_cond_signal(&javaFinishedCond);
pthread_mutex_unlock(&javaFinishedMutex);
return NULL;
}
Apparently JVM uses SIGBUS/SIGSEGV internally to control the app (?). I made mu debugger pass those signals to the app and everything is fine now.