JDK 21中jdk.VirtualThreadPinned事件未触发的问题求助
排查jdk.VirtualThreadPinned事件未触发的可能原因
1. 事件未通过JVM参数或API启用
jdk.VirtualThreadPinned属于JDK Flight Recorder(JFR)事件,默认处于禁用状态,必须主动启用:
- 启动测试时添加JVM参数,直接指定启用该事件:
或使用预设配置文件(profile配置默认包含该事件):-XX:StartFlightRecording=events=jdk.VirtualThreadPinned-XX:StartFlightRecording=settings=profile,filename=test-recording.jfr - 也可以在代码中通过JFR API动态启用:
EventType pinnedEventType = EventType.getEventType("jdk.VirtualThreadPinned"); if (pinnedEventType != null) { pinnedEventType.setEnabled(true); }
2. 同步块执行时间未达触发阈值
JVM不会对短暂持有锁的虚拟线程触发固定事件,默认阈值为20毫秒(可通过-Djdk.virtualThread.pinned.threshold=xxx调整)。如果你的测试同步块执行太快,比如空块或瞬时操作,不会触发事件。可以在同步块中添加延迟:
synchronized (lockObj) { Thread.sleep(50); // 超过默认阈值,确保触发判定 }
3. 事件监听逻辑存在疏漏
检查自定义监听器是否正确绑定到jdk.VirtualThreadPinned事件:
- 确认事件名称拼写完全正确,监听器注册时机早于虚拟线程执行:
try (Recording recording = new Recording()) { recording.addEventCallback("jdk.VirtualThreadPinned", event -> { // 事件处理逻辑 System.out.println("虚拟线程被固定"); }); recording.start(); // 启动虚拟线程执行同步块逻辑 Thread.ofVirtual().start(() -> { synchronized (lockObj) { try { Thread.sleep(50); } catch (InterruptedException e) {} } }); Thread.sleep(100); // 等待事件触发 }
4. JDK版本潜在bug
你使用的JDK21.0.3+7-LTS-152存在部分虚拟线程事件触发的已知问题,建议升级到JDK21的最新小版本(如21.0.4+7)再测试,确认是否是版本导致的事件不触发。
5. 虚拟线程执行上下文异常
如果虚拟线程被包装在ForkJoinPool或其他调度器中执行,可能会影响JVM对线程固定状态的判定,确保虚拟线程是直接通过Thread.ofVirtual().start()或ExecutorService.newVirtualThreadPerTaskExecutor()创建并执行同步逻辑。
内容的提问来源于stack exchange,提问作者ravenskater
相关产品推荐
相关产品推荐

