3

The app crashes if following function is called:

void on_log(JavaVM* vm, int level, const char *data) { printOnAndroid(level, data); pthread_t loggerThread; pthread_create(&loggerThread, NULL, attachThreadToJavaVMAndPrint, data); pthread_join(loggerThread, NULL); } void attachThreadToJavaVMAndPrint(JavaVM* vm, const char *data) { int isThreadAttached = attachJNIEnvToThread(vm); if (isThreadAttached == 1) { JNIEnv* env; (*vm)->GetEnv(vm, &env, APP_JNI_VERSION); jclass thisClass = (*env)->GetObjectClass(env, _loggerObject); jmethodID methodId = (*env)->GetMethodID(env, thisClass, "logFromC","(Ljava/lang/String;)V"); if (methodId != NULL) { jstring message = (*env)->NewStringUTF(env, data); (*env)->CallVoidMethod(env, _loggerObject, methodId, message); } (*vm)->DetachCurrentThread(vm); } } void printOnAndroid(int level, const char* data) { __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "XXXX %i, data %s", level, data); } int attachJNIEnvToThread(JavaVM* vm) { JNIEnv* env; JavaVMAttachArgs args; args.version = APP_JNI_VERSION; args.name = NULL; args.group = NULL; if ((*vm)->GetEnv(vm, &env, APP_JNI_VERSION) == JNI_EDETACHED) { jint attachResponse = (*vm)->AttachCurrentThread(vm, &env, &args); if ((*vm)->GetEnv(vm, &env, APP_JNI_VERSION) != JNI_OK) { return 0; } } return 1; } 

There is a macro:

 #define APP_JNI_VERSION JNI_VERSION_1_2 

As per logs, there is a crash when attachJNIEnvToThread(..) is called

EDIT:

It runs successfully on linux.. so may be there is something android specific that I am not aware of.

EDIT 2:

Changed the signature of the following:

 void * attachThreadToJavaVMAndPrint(void* dataArg) { JavaVM* vm = _vm; const char* data = (const char *)dataArg; int isThreadAttached = attachJNIEnvToThread(vm); if (isThreadAttached == 1) { JNIEnv* env; (*vm)->GetEnv(vm, &env, APP_JNI_VERSION); jclass thisClass = (*env)->GetObjectClass(env, _loggerObject); jmethodID methodId = (*env)->GetMethodID(env, thisClass, "logFromC","(Ljava/lang/String;)V"); if (methodId != NULL) { jstring message = (*env)->NewStringUTF(env, data); (*env)->CallVoidMethod(env, _loggerObject, methodId, message); } (*vm)->DetachCurrentThread(vm); } return 0; } 

This changes the log slightly and the crash is in attachThreadToJavaAndPrint(..)

EDIT 3:

This has been solved.. Final changes included Edit 2 + some changes in java code (not visible here (there were bugs in it))..

2
  • Is there still a crash if you do nothing in the thread (that is:commenting out all the code after the call to attachJNIEnvToThread)? Commented Feb 7, 2014 at 11:45
  • I removed everything but then it is still crashing.. Getting the following: /system/lib/libdvm.so (dvmAbort+67) 02-10 12:32:30.654 123-123/? I/DEBUG﹕ #01 pc 0000cecc /system/lib/libc.so 02-10 12:32:30.654 123-123/? I/DEBUG﹕ #02 pc 0000e5c0 /system/lib/libc.so (pthread_exit+80) 02-10 12:32:30.654 123-123/? I/DEBUG﹕ #03 pc 0000cbd4 /system/lib/libc.so (pthread_create+208) Commented Feb 10, 2014 at 7:29

2 Answers 2

1

First, make sure the parameter vm is correct in void on_log(JavaVM* vm, int level, const char *data). I saved the vm as an global variable in JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved), and my code can work:

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { g_vm = vm; } 

in the function for thread

{ ret = g_vm->AttachCurrentThread( (JNIEnv **) &env, NULL); } 
Sign up to request clarification or add additional context in comments.

3 Comments

how can i check if this is correct? m initializing in on_load(..) menthod.. also the call (*vm)->GetEnv(..) is able to run properly so its not null
I checked getenv for other thread (from which on_log(..) was called)and it is working properly.. so vm should be correct.. You are not returning any int in onload.. m returning JNI version 2.. and thus in attach call I cannot use NULL according to invocation api docs
I just showed you part of my code. To verify whether the vm is correct, you can logout the value of vm. import android.util.Log; and Log.i("VM", String.format("VM: 0x%x", vm));
1

The problematic place in your code is when you create thread. The thread function takes ONE pointer, not two.

So, you can either give it VM*, or data, or wrap them into some structure.

Example of wrapping:

struct params { JavaVM *vm; char *data; }; void on_log(JavaVM* vm, int level, const char *data) { struct params params = {vm, data}; printOnAndroid(level, data); pthread_t loggerThread; pthread_create(&loggerThread, NULL, attachThreadToJavaVMAndPrint, &params); pthread_join(loggerThread, NULL); } void * attachThreadToJavaVMAndPrint(void* arg) { struct params *params = arg; JavaVM* vm = params->vm; const char* data = params->data; ... 

Second problem is in thread attachment: you can't get JNIEnv before attaching to thread:

int attachJNIEnvToThread(JavaVM* vm) { JNIEnv* env; return (*vm)->AttachCurrentThread(vm, &env, NULL) ? 1 : 0; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.