解決JNI線程pthread_setname_np無效問題

C/C++都是使用pthread方法創建線程,這些線程和Java里的線程是不同,它們沒有JVM環境。通常的做法是通過 AttachCurrentThread 方法將當前線程附著到 Java 虛擬機上。

但是這些線程附著后,原來通過pthread_setname_np設置的線程名都無效了,取而代之的是Thread-xxx這類系統命名。

線程名可以通過lldb的bt all命令看到

為了弄清原因,我們看一下AttachCurrentThread的文檔說明:

https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env, void *thr_args);

Attaches the current thread to a Java VM. Returns a JNI interface pointer in the JNIEnv argument.

Trying to attach a thread that is already attached is a no-op.

A native thread cannot be attached simultaneously to two Java VMs.

When a thread is attached to the VM, the context class loader is the bootstrap loader.

LINKAGE:
Index 4 in the JavaVM interface function table.

PARAMETERS:
vm: the VM to which the current thread will be attached.

p_env: pointer to the location where the JNI interface pointer of the current thread will be placed.

thr_args: VM-specific thread attachment arguments.

In JDK 1.1, the second argument to AttachCurrentThread is always a pointer to JNIEnv. The third argument to AttachCurrentThread was reserved, and should be set to NULL.

In the JDK, you pass NULL as the third argument for 1.1 behavior, or pass a pointer to the following structure to specify additional information:

typedef struct JavaVMAttachArgs {
    jint version;  /* must be JNI_VERSION_1_2 */
    char *name;    /* the name of the thread as a modified UTF-8 string, or NULL */
    jobject group; /* global ref of a ThreadGroup object, or NULL */
} JavaVMAttachArgs
RETURNS:
Returns “0” on success; returns a negative number on failure.

thr_args用于設置VM相關的線程名,我們之所以以前設置的線程名失效,主要是在Attached的時候沒有給它賦值。
正確的代碼應該是:

#include <linux/prctl.h>
#include <sys/prctl.h>

char thread_name[128] = {0};
prctl(PR_GET_NAME, (char *)(thread_name));
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_4;  // version值請參考你的NDK,必須大于JNI_VERSION_1_2
args.name = (char *)thread_name;
args.group = NULL;

if ((*jvm)->AttachCurrentThread(jvm, &env, (void*)&args) == JNI_OK) {
}

另外,pthread_setname_np的名字不能超過16字節,所以請不要設一個太長的名字。

https://android.googlesource.com/platform/bionic/+/40eabe2/libc/bionic/pthread_setname_np.cpp

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容