2020import java .io .File ;
2121import java .io .IOException ;
2222import java .io .PrintStream ;
23+ import java .lang .invoke .MethodHandle ;
24+ import java .lang .invoke .MethodHandles ;
25+ import java .lang .invoke .MethodType ;
2326import java .lang .management .BufferPoolMXBean ;
2427import java .lang .management .LockInfo ;
2528import java .lang .management .ManagementFactory ;
@@ -88,7 +91,7 @@ public ThreadPair(Thread thread) {
8891 * terminated, its slot in the returned array is null.
8992 */
9093 List <Thread > threadList = new ArrayList <>(threads );
91- long [] threadIds = threadList .stream ().mapToLong (Thread :: getId ).toArray ();
94+ long [] threadIds = threadList .stream ().mapToLong (ThreadId :: get ).toArray ();
9295 ThreadMXBean threadMXBean = ManagementFactory .getThreadMXBean ();
9396 ThreadInfo [] threadInfos = threadMXBean .getThreadInfo (threadIds , true , true );
9497 for (int i = 0 ; i < threadList .size (); i ++) {
@@ -102,7 +105,7 @@ public ThreadPair(Thread thread) {
102105 if (p .threadInfo == null ) {
103106 Thread t = p .thread ;
104107 printStream .format ("\" %s\" Id=%d prio=%d %s%n" ,
105- t .getName (), t . getId ( ), t .getPriority (), t .getState ());
108+ t .getName (), ThreadId . get ( t ), t .getPriority (), t .getState ());
106109 for (StackTraceElement element : t .getStackTrace ()) {
107110 printStream .format ("\t at %s%n" , element );
108111 }
@@ -313,6 +316,17 @@ public static long getLongPid() {
313316 return Pid .PID .orElse (-1 );
314317 }
315318
319+ /**
320+ * Gets the thread id of the specified thread. For Java 19+, this method returns the
321+ * value of {@code Thread.threadId}; for Java 18-, this method returns the value of
322+ * {@code Thread.getId}.
323+ * @param thread the {@code thread} for which the id is to be returned
324+ * @return the {@code Thread} id; {@code -1} if an error was raised while obtaining the id
325+ */
326+ public static long threadId (Thread thread ) {
327+ return ThreadId .get (thread );
328+ }
329+
316330 /**
317331 * Returns an array contain a reference to all {@link Thread} instances in the JVM. Since the JVM is
318332 * not stopped, the returned array may miss threads or have no longer extant threads.
@@ -389,6 +403,52 @@ public static MaxDirectMemoryInfo getMaxDirectMemoryInfo() {
389403 return MaxDirectMemoryInfoHelper .INSTANCE ;
390404 }
391405
406+ /**
407+ * Handles using the JVM-appropriate method to obtain the id for a {@code Thread}.
408+ */
409+ private static class ThreadId {
410+ private static final MethodHandle THREAD_ID_METHOD ;
411+
412+ static {
413+ MethodHandles .Lookup lookup = MethodHandles .publicLookup ();
414+ MethodType longNiladic = MethodType .methodType (long .class );
415+ MethodHandle threadId ;
416+ try {
417+ // Thread.threadId is added in Java 19 as a replacement for Thread.getId
418+ threadId = lookup .findVirtual (Thread .class , "threadId" , longNiladic );
419+ } catch (NoSuchMethodException | IllegalAccessException e ) {
420+ try {
421+ // Thread.getId is deprecated in Java 19
422+ threadId = lookup .findVirtual (Thread .class , "getId" , longNiladic );
423+ } catch (NoSuchMethodException | IllegalAccessException ex ) {
424+ threadId = MethodHandles .constant (long .class , -1L );
425+
426+ System .err .format ("Failed to create handle for Thread 'id' method; calls to %s.threadId will return -1" , Diagnostics .class .getSimpleName ());
427+ ex .addSuppressed (e );
428+ ex .printStackTrace (System .err );
429+ }
430+ }
431+ THREAD_ID_METHOD = threadId ;
432+ }
433+
434+ /**
435+ * Gets the id of the specified {@code Thread}.
436+ * @param t the {@code Thread} for which the id is to be obtained
437+ * @return the {@code Thread} id; {@code -1} if there is an error obtaining the {@code Thread} id
438+ */
439+ private static long get (Thread t ) {
440+ try {
441+ return (long )THREAD_ID_METHOD .invoke (t );
442+ } catch (Error e ) {
443+ throw e ;
444+ } catch (Throwable throwable ) {
445+ System .err .format ("Failed obtain thread id from %s; returning -1" , THREAD_ID_METHOD );
446+ throwable .printStackTrace (System .err );
447+ return -1L ;
448+ }
449+ }
450+ }
451+
392452 /**
393453 * Determines the process identifier of the current process.
394454 */
0 commit comments