解决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 
#include 

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

你可能感兴趣的:(解决JNI线程pthread_setname_np无效问题)