On Thu, 10 Sep 2026 05:50:29 GMT, Denghui Dong <[email protected]> wrote:

>> Hi,
>> 
>> Please help review this change that fixes crash in 
>> ThreadSnapshot::initialize.
>> 
>> After [JDK-8323792](https://bugs.openjdk.org/browse/JDK-8323792), we can 
>> still see the same crash reported in 
>> [JDK-8374820](https://bugs.openjdk.org/browse/JDK-8374820) and 
>> [JDK-8346980](https://bugs.openjdk.org/browse/JDK-8346980).
>> 
>> Here is a reproducer:
>> 
>> 
>> import java.lang.management.ManagementFactory;
>> import java.lang.management.ThreadInfo;
>> import java.lang.management.ThreadMXBean;
>> import java.util.Arrays;
>> import java.util.Objects;
>> import java.util.concurrent.atomic.AtomicLong;
>> import java.util.concurrent.locks.LockSupport;
>> 
>> public class ThreadSnapshotRace {
>> 
>>     public static void main(String[] args) throws Exception {
>>         Thread producer = new Thread(() -> {
>>             AtomicLong counter = new AtomicLong();
>>             long total = 0;
>>             while (true) {
>>                 long c = counter.incrementAndGet();
>>                 total++;
>>                 Thread.ofVirtual().name("vthread").start(() -> {
>>                     counter.decrementAndGet(); 
>>                 });
>>                 if (total % 10_000_000 == 0) {
>>                     System.out.println(total);
>>                 }
>>                 if (c >= 20_000_000) {
>>                     do {
>>                         try {
>>                             Thread.sleep(50);
>>                         } catch (Exception e) {
>>                         }
>>                     } while (counter.get() > 0);
>>                 }
>>             }
>>         });
>>         producer.start();
>> 
>>         Thread.sleep(1000);
>> 
>>         Thread consumer = new Thread(() -> {
>>             ThreadMXBean bean = ManagementFactory.getThreadMXBean();
>>             long[] ids = carrierIds(bean);
>>             while (true) {
>>                 ThreadInfo[] infos = bean.getThreadInfo(ids);
>>                 if (infos.length == 0) {
>>                     System.out.println("?");
>>                 }
>>             }
>>         });
>>         consumer.start();
>>     }
>> 
>>     static long[] carrierIds(ThreadMXBean bean) {
>>         long[] all = bean.getAllThreadIds();
>>         long[] carriers = Arrays.stream(bean.getThreadInfo(all))
>>                 .filter(Objects::nonNull)
>>                 .filter(ti -> 
>> ti.getThreadName().startsWith("ForkJoinPool-1-worker"))
>>                 .mapToLong(ThreadInfo::getThreadId)
>>                 .toArray();
>>         return carriers;
>>     }
>> }
>>...
>
> Denghui Dong has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   add test

Running with the extra assert (updated above), I found 
`SafepointSynchronize::print_safepoint_timeout()` is calling 
`is_vthread_mounted()` from `JavaThread::print_on` and `Thread::print_on`, 
which is not safe either. We can fix them here with the same 
`java_lang_VirtualThread::is_instance()` check, so we can add the assert in 
`vthread_continuation()`, or I can do that in a separate fix if you prefer.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/32788#issuecomment-5627603982

Reply via email to