编写native方法实现java获取线程pid
在linux系统中进程是n(n>=1)个线程的集合,映射到实现层面即为task_struct的集合,其中每个task_struct代表一个线程,每个结构体有一个pid字段, 主线程的pid即为这个线程集合即进程的pid。
- java中获取进程的pid比较简单:
String name = ManagementFactory.getRuntimeMXBean().getName();
System.out.println(name);
result: 77668@xxxxxxxxxx // 77668即为进程id
- 如何获取某个线程的pid呢?可以按照下面的步骤编写native代码来获取,本文参考自Stack Overflow,并加上了注释。
- 编写java代码:GetThreadID.java
class GetThreadID {
// 声明native方法
public static native int get_tid();
static {
// 加载动态库文件,native方法就在这里面实现的
System.loadLibrary("GetThreadID");
}
// 搞了两个死循环,等下可看到两个cpu占用率为100%的线程
public static void main(String[] args) {
int tid = GetThreadID.get_tid();
System.out.println("main TID=" + tid);
new Thread(){
@Override
public void run() {
int tid = GetThreadID.get_tid();
System.out.println("TID=" + tid);
while (true){}
}
}.start();
while (true){}
}
}
- 实现native方法, 即编写c代码GetThreadID.c
#include <jni.h>
#include <syscall.h>
#include "GetThreadID.h"
JNIEXPORT jint JNICALL
Java_GetThreadID_get_1tid(JNIEnv *env, jobject obj) {
// 这里发起系统调用,读取上述task_struct结构体里的pid,估计实现就一行:return current->pid // current为指向当前线程(task_struct)的指针;
// 感觉系统调用的过程一定要好好研究下,
// __NR_gettid: 系统调用号码宏定义,查看系统文件/usr/include/asm/unistd_64.h文件可知其为186,即下面的代码等价于:syscall(186)
jint tid = syscall(__NR_gettid);
return tid;
}
- 编译代码javac GetThreadID.java, 生成头文件:javah GetThreadID,
- 生成动态链接库:
gcc -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -fPIC -shared GetThreadID.c -o libGetThreadID.so
- 执行代码 java GetThreadID,屏幕会输出main线程和thread线程的pid,同时linux下使用top -H命令,能看到有两个cpu占用率为100%的线程。