Skip to content

Conversation

@YaSuenag
Copy link
Member

@YaSuenag YaSuenag commented Nov 13, 2025

We've fixed mixed mode jstack for the debuggee running with -Xcomp in JDK-8370176, but it was not enough. We need to handle like unifying CFrame and Frame in stack unwinding as possible, and need to change how to get caller SP/FP from stack.

This PR works fine on both Linux AMD64 and Linux AArch64. All of hotspot/jtreg/serviceability/sa tests have been passed on both platforms.

Big thanks to @pchilano for your help!


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8371194: serviceability/sa/TestJhsdbJstackMixedWithXComp.java failing (Bug - P4)

Reviewers

Contributors

  • Patricio Chilano Mateo <pchilanomate@openjdk.org>

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/28284/head:pull/28284
$ git checkout pull/28284

Update a local copy of the PR:
$ git checkout pull/28284
$ git pull https://git.openjdk.org/jdk.git pull/28284/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 28284

View PR using the GUI difftool:
$ git pr show -t 28284

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/28284.diff

Using Webrev

Link to Webrev Comment

Co-authored-by: Patricio Chilano Mateo <pchilanomate@openjdk.org>
@bridgekeeper
Copy link

bridgekeeper bot commented Nov 13, 2025

👋 Welcome back ysuenaga! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Nov 13, 2025

@YaSuenag This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8371194: serviceability/sa/TestJhsdbJstackMixedWithXComp.java failing

Co-authored-by: Patricio Chilano Mateo <pchilanomate@openjdk.org>
Reviewed-by: cjplummer, pchilanomate

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 272 new commits pushed to the master branch:

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the serviceability serviceability-dev@openjdk.org label Nov 13, 2025
@openjdk
Copy link

openjdk bot commented Nov 13, 2025

@YaSuenag The following label will be automatically applied to this pull request:

  • serviceability

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 13, 2025
@YaSuenag
Copy link
Member Author

/contributor add @pchilano

@openjdk
Copy link

openjdk bot commented Nov 13, 2025

@YaSuenag
Contributor Patricio Chilano Mateo <pchilanomate@openjdk.org> successfully added.

@mlbridge
Copy link

mlbridge bot commented Nov 13, 2025

Webrevs

@YaSuenag
Copy link
Member Author

This PR is for Linux, other platforms (Windows, Mac) would not work. However I think it is not a problem because Windows and Mac has not been supported mixed jstack originally.

Copy link
Contributor

@pchilano pchilano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix looks good to me (can't comment on the PPC and RISCV parts though).

* @bug 8370176
* @requires vm.hasSA
* @requires os.family == "linux"
* @requires os.arch == "amd64"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we run the test on AArch64 now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR works on Linux AArch64, but I'm not sure because previous change (#27885) worked on some Linux AArch64, but there are some platforms whch did not work. Thus I think it is better to keep this test for Linux AMD64 only.

I couldn't reproduce the problem on Fedora Rawhide on Raspberry Pi 4, but there might be some issue because SA does not have DWARF parser for AArch 64 - it means the native we cannot find sender frame which depends on DWARF, does not use FP as frame pointer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I enabled this test for linux-aarch64 and it seems to pass our testing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw the problem on VMError::report_and_die because its frame could not be unwinded without DWARF.

I have not seen the problem in other place, but I'm concerned the test fails on some Linux AArch64 platforms. Thus I think it is better to wait enabling the test until SA supports DWARF.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Nov 17, 2025
@plummercj
Copy link
Contributor

On macosx I'm seeing the following when running ClhsdbPStack.java:

hsdb> hsdb> + verbose true
hsdb> + pstack -v
Deadlock Detection:

No deadlocks found.

Not available for Mac OS X processes
hsdb> + quit

The "Not available for Mac OS X processes" message is expected when running on a macosx process, but in this case the test is running the core version of the test, so SA is acting on a core file. The test goes on to fail because there are no threads in the output.

The message is generated by PStack.java whenever the thread list is null and it is running on OSX. In that case it assumes the reason the thread list is null is because it is running on a macosx process. It's not clear to me why the thread list is null. I don't see any changes that look like they could cause that.

This happens with both x64 and aarch64, although you need to remove the test from the problem list for macosx-aarch64 to get it to reproduce. macosx-x64 is not problem listed.

@YaSuenag
Copy link
Member Author

The message is generated by PStack.java whenever the thread list is null and it is running on OSX.

Maybe it is a side effect of deleting initJFrameCache() from PStack.java.
I do not have Mac, so I cannot verify the following...

BsdDebuggerLocal::threadList would be filled in getJavaThreadsInfo(), and it is eventually called through a chain of calls starting from BsdThread::getContext(). It is eventually called by getCurrentFrameGuess() from PStack::initJFrameCache().

I think it is better to separate BsdDebuggerLocal::getJavaThreadsInfo() - filling threadList can move to getThreadList() because it is not needed in getJavaThreadsInfo().

@YaSuenag
Copy link
Member Author

@plummercj Can you try this patch on your Mac? You can apply it to this PR branch.

diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
index 10f6881d010..f091b22f9d7 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
 package sun.jvm.hotspot.debugger.bsd;

 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.stream.IntStream;

 import sun.jvm.hotspot.debugger.Address;
 import sun.jvm.hotspot.debugger.DebuggerBase;
@@ -75,10 +77,11 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
     // CDebugger support
     private BsdCDebugger cdbg;

-    // threadList and loadObjectList are filled by attach0 method
-    private List<ThreadProxy> threadList;
+    // loadObjectList are filled by attach0 method
     private List<LoadObject> loadObjectList;

+    private List<JavaThread> javaThreadList;
+
     // called by native method lookupByAddress0
     private ClosestSymbol createClosestSymbol(String name, long offset) {
        return new ClosestSymbol(name, offset);
@@ -244,7 +247,7 @@ private void findABIVersion() throws DebuggerException {
     /** From the Debugger interface via JVMDebugger */
     public synchronized void attach(int processID) throws DebuggerException {
         checkAttached();
-        threadList = new ArrayList<>();
+        javaThreadList = new ArrayList<>();
         loadObjectList = new ArrayList<>();
         class AttachTask implements WorkerThreadTask {
            int pid;
@@ -264,7 +267,7 @@ public void doit(BsdDebuggerLocal debugger) {
     /** From the Debugger interface via JVMDebugger */
     public synchronized void attach(String execName, String coreName) {
         checkAttached();
-        threadList = new ArrayList<>();
+        javaThreadList = new ArrayList<>();
         loadObjectList = new ArrayList<>();
         attach0(execName, coreName);
         attached = true;
@@ -278,7 +281,7 @@ public synchronized boolean detach() {
             return false;
         }

-        threadList = null;
+        javaThreadList = null;
         loadObjectList = null;

         if (isCore) {
@@ -492,7 +495,25 @@ public Address newAddress(long value) {
     /** From the BsdCDebugger interface */
     public List<ThreadProxy> getThreadList() {
       requireAttach();
-      return threadList;
+
+      if (javaThreadList == null) {
+        return null;
+      }
+      if (!isCore) {
+        // TODO: thread list is now supported for corefile only.
+        return Collections.emptyList();
+      }
+
+      if (javaThreadList.isEmpty()) {
+        Threads threads = VM.getVM().getThreads();
+        IntStream.range(0, threads.getNumberOfThreads())
+                 .mapToObj(threads::getJavaThreadAt)
+                 .forEach(javaThreadList::add);
+      }
+
+      return javaThreadList.stream()
+                           .map(t -> t.getThreadProxy())
+                           .toList();
     }

     /** From the BsdCDebugger interface */
@@ -561,21 +582,16 @@ public void doit(BsdDebuggerLocal debugger) {
     /** this functions used for core file reading and called from native attach0,
         it returns an array of long integers as
         [thread_id, stack_start, stack_end, thread_id, stack_start, stack_end, ....] for
-        all java threads recorded in Threads. Also adds the ThreadProxy to threadList */
+        all java threads recorded in Threads. */
     public long[] getJavaThreadsInfo() {
         requireAttach();
-        Threads threads = VM.getVM().getThreads();
-        int len = threads.getNumberOfThreads();
-        long[] result = new long[len * 3];    // triple
+        long[] result = new long[javaThreadList.size() * 3];    // triple
         long beg, end;
         int i = 0;
-        for (int k = 0; k < threads.getNumberOfThreads(); k++) {
-            JavaThread t = threads.getJavaThreadAt(k);
+        for (var t : javaThreadList) {
             end = t.getStackBaseValue();
             beg = end - t.getStackSize();
-            BsdThread bsdt = (BsdThread)t.getThreadProxy();
-            long uid = bsdt.getUniqueThreadId();
-            if (threadList != null) threadList.add(bsdt);
+            long uid = ((BsdThread)t.getThreadProxy()).getUniqueThreadId();
             result[i] = uid;
             result[i + 1] = beg;
             result[i + 2] = end;

@plummercj
Copy link
Contributor

With your diffs ClhsdbPStack.java is passing but now I'm seeing issues with the following 3 core file tests on both aarch64 and x64:

serviceability/sa/ClhsdbFindPC.java#xcomp-core
serviceability/sa/ClhsdbFindPC.java#no-xcomp-core
serviceability/sa/ClhsdbCDSCore.java

In the log it is having trouble with the stack trace:

hsdb> + jstack -v
Deadlock Detection:

No deadlocks found.

"main" #3 prio=5 tid=0x00007fa48a809010 nid=10499 runnable [0x000070000b780000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_in_native

Error occurred during stack walking:
sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
	at jdk.hotspot.agent/sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.getThreadIntegerRegisterSet0(Native Method)
	at jdk.hotspot.agent/sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.getThreadIntegerRegisterSet(BsdDebuggerLocal.java:462)
	at jdk.hotspot.agent/sun.jvm.hotspot.debugger.bsd.BsdThread.getContext(BsdThread.java:68)
	at jdk.hotspot.agent/sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess.getCurrentFrameGuess(BsdAMD64JavaThreadPDAccess.java:98)
	at jdk.hotspot.agent/sun.jvm.hotspot.runtime.JavaThread.getCurrentFrameGuess(JavaThread.java:266)
	at jdk.hotspot.agent/sun.jvm.hotspot.runtime.JavaThread.getLastJavaVFrameDbg(JavaThread.java:228)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.StackTrace.run(StackTrace.java:81)
	at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor$23.doit(CommandProcessor.java:1020)
	at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor.executeCommand(CommandProcessor.java:2088)
	at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor.executeCommand(CommandProcessor.java:2058)
	at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor.run(CommandProcessor.java:1929)
	at jdk.hotspot.agent/sun.jvm.hotspot.CLHSDB.run(CLHSDB.java:113)
	at jdk.hotspot.agent/sun.jvm.hotspot.CLHSDB.main(CLHSDB.java:45)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runCLHSDB(SALauncher.java:285)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:507)

This repeats for every thread.

@YaSuenag
Copy link
Member Author

@plummercj Thanks a lot for your report! The error what you saw is caused that thread list wasn't made in attach().
I think following patch goes well... Can you try it?

diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
index 10f6881d010..7c71dcd0ca5 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
 package sun.jvm.hotspot.debugger.bsd;

 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.stream.IntStream;

 import sun.jvm.hotspot.debugger.Address;
 import sun.jvm.hotspot.debugger.DebuggerBase;
@@ -75,10 +77,11 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
     // CDebugger support
     private BsdCDebugger cdbg;

-    // threadList and loadObjectList are filled by attach0 method
-    private List<ThreadProxy> threadList;
+    // loadObjectList are filled by attach0 method
     private List<LoadObject> loadObjectList;

+    private List<JavaThread> javaThreadList;
+
     // called by native method lookupByAddress0
     private ClosestSymbol createClosestSymbol(String name, long offset) {
        return new ClosestSymbol(name, offset);
@@ -241,10 +244,16 @@ private void findABIVersion() throws DebuggerException {
         }
     }

+    private List<JavaThread> generateJavaThreadList() {
+      Threads threads = VM.getVM().getThreads();
+      return IntStream.range(0, threads.getNumberOfThreads())
+                      .mapToObj(threads::getJavaThreadAt)
+                      .toList();
+    }
+
     /** From the Debugger interface via JVMDebugger */
     public synchronized void attach(int processID) throws DebuggerException {
         checkAttached();
-        threadList = new ArrayList<>();
         loadObjectList = new ArrayList<>();
         class AttachTask implements WorkerThreadTask {
            int pid;
@@ -253,6 +262,10 @@ public void doit(BsdDebuggerLocal debugger) {
               debugger.attached = true;
               debugger.isCore = false;
               findABIVersion();
+
+              // TODO: thread list on macOS is now supported for corefile only.
+              debugger.javaThreadList = debugger.isDarwin ? Collections.emptyList()
+                                                          : generateJavaThreadList();
            }
         }

@@ -264,12 +277,12 @@ public void doit(BsdDebuggerLocal debugger) {
     /** From the Debugger interface via JVMDebugger */
     public synchronized void attach(String execName, String coreName) {
         checkAttached();
-        threadList = new ArrayList<>();
         loadObjectList = new ArrayList<>();
         attach0(execName, coreName);
         attached = true;
         isCore = true;
         findABIVersion();
+        javaThreadList = generateJavaThreadList();
     }

     /** From the Debugger interface via JVMDebugger */
@@ -278,7 +291,7 @@ public synchronized boolean detach() {
             return false;
         }

-        threadList = null;
+        javaThreadList = null;
         loadObjectList = null;

         if (isCore) {
@@ -492,7 +505,9 @@ public Address newAddress(long value) {
     /** From the BsdCDebugger interface */
     public List<ThreadProxy> getThreadList() {
       requireAttach();
-      return threadList;
+      return javaThreadList.stream()
+                           .map(JavaThread::getThreadProxy)
+                           .toList();
     }

     /** From the BsdCDebugger interface */
@@ -561,21 +576,16 @@ public void doit(BsdDebuggerLocal debugger) {
     /** this functions used for core file reading and called from native attach0,
         it returns an array of long integers as
         [thread_id, stack_start, stack_end, thread_id, stack_start, stack_end, ....] for
-        all java threads recorded in Threads. Also adds the ThreadProxy to threadList */
+        all java threads recorded in Threads. */
     public long[] getJavaThreadsInfo() {
         requireAttach();
-        Threads threads = VM.getVM().getThreads();
-        int len = threads.getNumberOfThreads();
-        long[] result = new long[len * 3];    // triple
+        long[] result = new long[javaThreadList.size() * 3];    // triple
         long beg, end;
         int i = 0;
-        for (int k = 0; k < threads.getNumberOfThreads(); k++) {
-            JavaThread t = threads.getJavaThreadAt(k);
+        for (var t : javaThreadList) {
             end = t.getStackBaseValue();
             beg = end - t.getStackSize();
-            BsdThread bsdt = (BsdThread)t.getThreadProxy();
-            long uid = bsdt.getUniqueThreadId();
-            if (threadList != null) threadList.add(bsdt);
+            long uid = ((BsdThread)t.getThreadProxy()).getUniqueThreadId();
             result[i] = uid;
             result[i + 1] = beg;
             result[i + 2] = end;

@plummercj
Copy link
Contributor

 stderr: [Exception in thread "main" java.lang.RuntimeException: VM.initialize() was not yet called
	at jdk.hotspot.agent/sun.jvm.hotspot.runtime.VM.getVM(VM.java:576)
	at jdk.hotspot.agent/sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.generateJavaThreadList(BsdDebuggerLocal.java:248)
	at jdk.hotspot.agent/sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal.attach(BsdDebuggerLocal.java:285)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.attachDebugger(HotSpotAgent.java:638)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupDebuggerDarwin(HotSpotAgent.java:624)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.setupDebugger(HotSpotAgent.java:378)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.go(HotSpotAgent.java:343)
	at jdk.hotspot.agent/sun.jvm.hotspot.HotSpotAgent.attach(HotSpotAgent.java:157)
	at jdk.hotspot.agent/sun.jvm.hotspot.CLHSDB.attachDebugger(CLHSDB.java:211)
	at jdk.hotspot.agent/sun.jvm.hotspot.CLHSDB.run(CLHSDB.java:70)
	at jdk.hotspot.agent/sun.jvm.hotspot.CLHSDB.main(CLHSDB.java:45)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runCLHSDB(SALauncher.java:285)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:507)

VM.initialize() is not triggered until after HotSpotAgent.setupDebugger() returns:

    private void go() {
        setupDebugger();
        setupVM();
    }

@YaSuenag
Copy link
Member Author

Ok, I confirmed VM.initialize() would be called at the end of setupVM(). So I updated a patch for BsdDebuggerLocal to initialize thread list in lazily. Can you try it again? Sorry for the trouble.

diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
index 10f6881d010..891ebc91f49 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
 package sun.jvm.hotspot.debugger.bsd;

 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.stream.IntStream;

 import sun.jvm.hotspot.debugger.Address;
 import sun.jvm.hotspot.debugger.DebuggerBase;
@@ -75,10 +77,11 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
     // CDebugger support
     private BsdCDebugger cdbg;

-    // threadList and loadObjectList are filled by attach0 method
-    private List<ThreadProxy> threadList;
+    // loadObjectList are filled by attach0 method
     private List<LoadObject> loadObjectList;

+    private List<JavaThread> javaThreadList;
+
     // called by native method lookupByAddress0
     private ClosestSymbol createClosestSymbol(String name, long offset) {
        return new ClosestSymbol(name, offset);
@@ -241,10 +244,21 @@ private void findABIVersion() throws DebuggerException {
         }
     }

+    private void fillJavaThreadList() {
+      // TODO: thread list on macOS is now supported for corefile only.
+      if (!isCore && isDarwin) {
+          javaThreadList = Collections.emptyList();
+      } else {
+          Threads threads = VM.getVM().getThreads();
+          javaThreadList =  IntStream.range(0, threads.getNumberOfThreads())
+                            .mapToObj(threads::getJavaThreadAt)
+                            .toList();
+      }
+    }
+
     /** From the Debugger interface via JVMDebugger */
     public synchronized void attach(int processID) throws DebuggerException {
         checkAttached();
-        threadList = new ArrayList<>();
         loadObjectList = new ArrayList<>();
         class AttachTask implements WorkerThreadTask {
            int pid;
@@ -264,7 +278,6 @@ public void doit(BsdDebuggerLocal debugger) {
     /** From the Debugger interface via JVMDebugger */
     public synchronized void attach(String execName, String coreName) {
         checkAttached();
-        threadList = new ArrayList<>();
         loadObjectList = new ArrayList<>();
         attach0(execName, coreName);
         attached = true;
@@ -278,7 +291,7 @@ public synchronized boolean detach() {
             return false;
         }

-        threadList = null;
+        javaThreadList = null;
         loadObjectList = null;

         if (isCore) {
@@ -492,7 +505,12 @@ public Address newAddress(long value) {
     /** From the BsdCDebugger interface */
     public List<ThreadProxy> getThreadList() {
       requireAttach();
-      return threadList;
+      if (javaThreadList == null) {
+        fillJavaThreadList();
+      }
+      return javaThreadList.stream()
+                           .map(JavaThread::getThreadProxy)
+                           .toList();
     }

     /** From the BsdCDebugger interface */
@@ -561,21 +579,19 @@ public void doit(BsdDebuggerLocal debugger) {
     /** this functions used for core file reading and called from native attach0,
         it returns an array of long integers as
         [thread_id, stack_start, stack_end, thread_id, stack_start, stack_end, ....] for
-        all java threads recorded in Threads. Also adds the ThreadProxy to threadList */
+        all java threads recorded in Threads. */
     public long[] getJavaThreadsInfo() {
         requireAttach();
-        Threads threads = VM.getVM().getThreads();
-        int len = threads.getNumberOfThreads();
-        long[] result = new long[len * 3];    // triple
+        if (javaThreadList == null) {
+            fillJavaThreadList();
+        }
+        long[] result = new long[javaThreadList.size() * 3];    // triple
         long beg, end;
         int i = 0;
-        for (int k = 0; k < threads.getNumberOfThreads(); k++) {
-            JavaThread t = threads.getJavaThreadAt(k);
+        for (var t : javaThreadList) {
             end = t.getStackBaseValue();
             beg = end - t.getStackSize();
-            BsdThread bsdt = (BsdThread)t.getThreadProxy();
-            long uid = bsdt.getUniqueThreadId();
-            if (threadList != null) threadList.add(bsdt);
+            long uid = ((BsdThread)t.getThreadProxy()).getUniqueThreadId();
             result[i] = uid;
             result[i + 1] = beg;
             result[i + 2] = end;

@plummercj
Copy link
Contributor

It's passing now.

@YaSuenag
Copy link
Member Author

@plummercj Thanks a lot! I pushed the change to this PR.

@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Nov 20, 2025
@YaSuenag
Copy link
Member Author

PING: could you review this?

@plummercj
Copy link
Contributor

PING: could you review this?

Sorry I didn't have a chance to get to this yet. I'm on holiday the rest of the week. I should be able to look at it on Monday. I did run your changes through most of our relevant CI testing, and everything passed.

Copy link
Contributor

@plummercj plummercj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks good. I made one very minor request for a comment fix. Thanks for all your efforts here1

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Dec 1, 2025
…sd/BsdDebuggerLocal.java

Co-authored-by: Chris Plummer <chris.plummer@oracle.com>
@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Dec 1, 2025
@YaSuenag
Copy link
Member Author

YaSuenag commented Dec 1, 2025

Thanks a lot for your review!
I applied the suggestion from Chris, and it made new commit. So could you approve this PR again? @pchilano @plummercj

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Dec 2, 2025
@YaSuenag
Copy link
Member Author

YaSuenag commented Dec 2, 2025

Thanks a lot for your review & help!

/integrate

@openjdk
Copy link

openjdk bot commented Dec 2, 2025

Going to push as commit d3083ac.
Since your change was applied there have been 281 commits pushed to the master branch:

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Dec 2, 2025
@openjdk openjdk bot closed this Dec 2, 2025
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Dec 2, 2025
@openjdk
Copy link

openjdk bot commented Dec 2, 2025

@YaSuenag Pushed as commit d3083ac.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@dholmes-ora
Copy link
Member

This PR works fine on both Linux AMD64 and Linux AArch64. All of hotspot/jtreg/serviceability/sa tests have been passed on both platforms.

@YaSuenag it doesn't seem to work on macOS however. We get an exception moving from the native frames to Java frames:

"Reference Handler" #15 daemon prio=10 tid=0x00000009f3091e10 nid=29955 waiting on condition [0x000000017059e000]
   java.lang.Thread.State: RUNNABLE
   JavaThread state: _thread_blocked
0x00000001890b64f8		????????
0x00000001083f8810	__ZN15PlatformMonitor4waitEy + 0x94
0x000000010836f60c	__ZN7Monitor4waitEy + 0x154
0x0000000107fa19dc	_JVM_WaitForReferencePendingList + 0x108
0x00000001192b5a48	sun.jvm.hotspot.utilities.UnsupportedPlatformException
	at jdk.hotspot.agent/sun.jvm.hotspot.debugger.cdbg.CFrame.toFrame(CFrame.java:78)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.PStack.getJavaNames(PStack.java:248)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.PStack.run(PStack.java:135)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.PStack.run(PStack.java:65)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.PStack.run(PStack.java:60)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.JStack.run(JStack.java:67)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.startInternal(Tool.java:278)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.start(Tool.java:241)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.Tool.execute(Tool.java:134)
	at jdk.hotspot.agent/sun.jvm.hotspot.tools.JStack.runWithArgs(JStack.java:90)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runJSTACK(SALauncher.java:306)
	at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:507)

Bug is being filed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integrated Pull request has been integrated serviceability serviceability-dev@openjdk.org

Development

Successfully merging this pull request may close these issues.

4 participants