Получение идентификатора потока для потоков Java в Linux

У меня есть приложение Java, где создаются некоторые потоки (черезnew Thread()). С помощьюps Я вижу, что они имеют разные идентификаторы потоков (столбец LWP), и я хотел бы получить эти идентификаторы из приложения Java.

В большинстве сообщений, связанных с этой темой, которые я нашел (например,этот), решение заключается в использованииManagementFactory.getRuntimeMXBean().getName().

Однако использование этого метода дает мне PID основного потока (даже если я вызываю его из одного из потоков), поэтому это не решает мою проблему.

Есть ли способ получить идентификатор потока для каждогоThread созданный приложением?

Можно ли использовать JNI для этого? Если как-то я мог бы взаимодействовать с функцией C, где я мог бы вызватьsyscall(__NR_gettid), что может решить мою проблему. Меня действительно не волнует переносимость, поэтому я полностью согласен с решением, которое будет работать только на Linux-машине.

UPDATE: Я на самом деле решил свою проблему с помощью JNI. Подробности объясняются в моем ответе. Спасибо всем за ваши предложения / комментарии.

 nhahtdh27 июн. 2012 г., 12:44
Поток Java может не соответствовать фактическому потоку в ОС.
 Niklas B.27 июн. 2012 г., 12:50
@betabandido: Итак, вы пытались реализовать эту функцию JNI? Или мы должны сделать это для вас?
 betabandido27 июн. 2012 г., 12:49
@nhahtdh Я не уверен на 100%, как потоки Java отображаются на потоки Linux, но, по крайней мере, в моей системе у них есть заданный идентификатор потока, как у pthread. Как я уже сказал, я не ищу портативное решение.
 Niklas B.27 июн. 2012 г., 12:53
@betabandido: вам обязательно стоит попробовать. Я не понимаю, почему это не должно работать.
 betabandido27 июн. 2012 г., 12:52
@NiklasB. Я не просил об этом. Поскольку я больше не привык писать код на Java и никогда не касался JNI, я просто хотел узнать, является ли это приемлемым вариантом. Если ответ да, я обязательно посмотрю на это сам.

Ответы на вопрос(3)

Этот пост в блоге предоставляет метод отображения из идентификаторов потока Java в идентификаторы LWP.

Суть этого в том, что идентификатор NLWP отображается на идентификатор потока Java.

 05 авг. 2016 г., 15:39
Пожалуйста, не публиковать ссылки только ответы.
 06 авг. 2016 г., 10:25
@ Gustavohenke: Спасибо за очень своевременный комментарий. ;-)
 27 июн. 2012 г., 12:59
@NiklasB: я знаю. Моя точка зрения заключалась в том, что это, вероятно, может быть сделано автоматически, если OP хочет сопоставить идентификаторы потока с идентификатором NLWP вместо идентификатора LWP.
 betabandido27 июн. 2012 г., 13:00
@SeanReilly Это определенно выглядит многообещающе. Как вы говорите, это может быть автоматизировано. Я буду исследовать этот путь, а также JNI (который был бы более прямым, но я пока не знаю, будет ли он работать). Спасибо!
 27 июн. 2012 г., 12:56
Я думаю, что сообщение в блоге говорит оmanually отображение потоков. OP хочет сделать это автоматически из Java
Решение Вопроса

что JNI - лучший способ решить мою проблему. В качестве ссылки я выкладываю код и собираю для него инструкции (основанные например в Википедии):

Класс Java, ответственный за интерфейс с кодом C (GetThreadID.java):

public class GetThreadID {
    public static native int get_tid();

    static {
        System.loadLibrary("GetThreadID");
    }
}

C-файл, ответственный за получение идентификатора потока (GetThread.c):

#include <jni.h>
#include <syscall.h>
#include "GetThreadID.h"

JNIEXPORT jint JNICALL
Java_GetThreadID_get_1tid(JNIEnv *env, jobject obj) {
    jint tid = syscall(__NR_gettid);
    return tid;
}

Пример того, как использоватьGetThreadID учебный класс:

class Main {
    public static void main(String[] args) {
        int tid = GetThreadID.get_tid();
        System.out.println("TID=" + tid);
    }
}

И наконец, инструкция по сборке (javah автоматически генерируетGetThreadID.h):

JAVA_HOME=$(readlink -f /usr/bin/javac | sed "s:bin/javac::")
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
javac GetThreadID.java
javah GetThreadID

gcc -I${JAVA_HOME}/include -fPIC -shared GetThreadID.c -o libGetThreadID.so
javac Main.java
java Main
 03 дек. 2018 г., 09:43
Я думаю, что инструкция gcc здесь должна быть gcc -I $ {JAVA_HOME} / include -I $ {JAVA_HOME} / include / linux -fPIC -shared GetThread.c -o libGetThreadID.so теперь через несколько дней: D!
 27 июн. 2012 г., 17:50
Очень приятно, спасибо за продолжение. Я подозревал, что это не будет слишком большой работой :) Я думаю, что вы должны принять здесь свой собственный ответ, так как это, безусловно, лучший ответ.
 03 дек. 2018 г., 10:59
Очевидно, это не сработает, если вы пропустите часть JAVA_HOME. Особенно, если вы уже установили JAVA_HOME. Но если вы будете следовать инструкциям плюс мои модификации, это работает.

ов, работающих в Java). Из вашего кода Java вы можете позвонитьThread#getId() и положить в необходимые журналы.

Thread.currentThread().getId();

Для получения идентификатора процесса вы можете попробовать это.ИСТОЧНИК

    byte[] bo = new byte[100];
    String[] cmd = { "bash", "-c", "echo $PPID" };
    Process p=null;
    try {
        p = Runtime.getRuntime().exec(cmd);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    try {
        p.getInputStream().read(bo);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       
   System.out.println(new String(bo));
 27 июн. 2012 г., 12:56
@betabandido я обновил свой ответ
 betabandido27 июн. 2012 г., 12:48
Я уже пробовал это, но он дает внутренний идентификатор, а не идентификатор потока, как видно в Linux. Таким образом, это не решает мой вопрос. Спасибо, в любом случае.

Ваш ответ на вопрос