11

I have a Java application where some threads are created (via new Thread()). Using ps I can see they have different thread IDs (LWP column) and I would like to obtain those IDs from within the Java application.

In most of the posts related to this topic that I have found (e.g., this one), the solution is to use ManagementFactory.getRuntimeMXBean().getName().

Using that method, however, gives me the PID of the main thread (even if I call it from one of the threads), so it is not really solving my problem.

Is there any way to obtain the thread ID for every single Thread created by an application?

Would it be possible to use JNI to accomplish it? If somehow I could interface to a C function where I could call syscall(__NR_gettid), that could solve my problem. I really do not care about portability, so I am totally okay with a solution that would only work for a Linux machine.

UPDATE: I have actually solved my problem by using JNI. Details are explained in my answer. Thank you all for your suggestions/comments.

Community
  • 1
  • 1
betabandido
  • 18,946
  • 11
  • 62
  • 76
  • 1
    Java Thread may not correspond to an actual thread on the OS. – nhahtdh Jun 27 '12 at 10:44
  • @nhahtdh I am not 100% sure how Java threads map to Linux threads, but at least in my system, they have a given thread ID as a pthread would have. As I said, I am not really looking for a portable solution. – betabandido Jun 27 '12 at 10:49
  • @betabandido: So, have you tried to implement that JNI function? Or are we supposed to do that for you? – Niklas B. Jun 27 '12 at 10:50
  • @NiklasB. I was not asking for that. Since I am not really used to write Java code anymore, and I have never touched JNI, I just wanted to know if it is a viable option. If the answer is yes, I will definitely look at it myself. – betabandido Jun 27 '12 at 10:52
  • @betabandido: You should definitely try it out. I don't see why that should not work. – Niklas B. Jun 27 '12 at 10:53
  • Something I found while searching for a definitive answer: http://www.coderanch.com/t/561229/threads/java/relationship-between-java-thread-native – nhahtdh Jun 27 '12 at 10:54
  • @NiklasB. Okay, I will implement it and see if it works. Thanks. – betabandido Jun 27 '12 at 10:55
  • @NiklasB. Done :) Using JNI was simpler than what I expected. – betabandido Jun 27 '12 at 13:48

2 Answers2

12

In the end, I found the JNI way to be the best one to solve my problem. As a reference, I post the code and build instructions for it (based on the example at Wikipedia):

Java class responsible to interface to the C code (GetThreadID.java):

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

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

C file responsible to obtain the thread ID (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;
}

An example of how to use GetThreadID class:

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

And finally, the build instructions (javah automatically generates 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
betabandido
  • 18,946
  • 11
  • 62
  • 76
  • Very nice, thanks for the follow-up. I suspected it wouldn't be too much work :) I think you should accept your own answer here, as it's definitely the best answer. – Niklas B. Jun 27 '12 at 15:50
  • I think the gcc instruction here should be gcc -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -fPIC -shared GetThread.c -o libGetThreadID.so now a days :D! – Artanis Zeratul Dec 03 '18 at 08:43
  • Apparently this won't work if you will omit JAVA_HOME part. Specially if you have set the JAVA_HOME already. But if you follow the instructions plus my modifications this works. – Artanis Zeratul Dec 03 '18 at 09:59
3

This blog post provides a method of mapping from java thread ids to LWP ids.

The gist of it seems to be that the NLWP id maps to the java thread id.

Sean Reilly
  • 21,526
  • 4
  • 48
  • 62
  • I think that blog post talks about *manually* mapping the threads. OP wants to do it automatically from within Java – Niklas B. Jun 27 '12 at 10:56
  • @NiklasB: I know. My point was that it probably can be done automatically if the OP is willing to map the thread ids to NLWP id instead of LWP id. – Sean Reilly Jun 27 '12 at 10:59
  • @SeanReilly This definitely looks promising. As you are saying, it could be automated. I will explore this way, as well as the JNI (which would be more direct, but I do not know yet whether it will work). Thanks! – betabandido Jun 27 '12 at 11:00
  • Please don't post link only answers. – gustavohenke Aug 05 '16 at 13:39
  • @gustavohenke: Thanks for the very timely comment. ;-) – Sean Reilly Aug 06 '16 at 08:25