揭秘JDK 21 faketime演练CPU拉满的迷局
问题背景
业务团队需要进行跨年演练,主要通过faketime来模拟未来特定时间点,我们在演练过程中出现CPU上升异常,最终拉满CPU配额,触发CPU throttle现象。
上述CPU拉满现象在JDK 21版本(容器镜像为AlmaLinux 9)可以稳定复现
1 | // 同事提供的复现代码如下所示 |
通过Tomcat环境中的自定义脚本/opt/tomcat/bin/extraenv.sh
,用于设置额外的环境变量或运行自定义初始化逻辑,faketime(0.9.10)相关配置如下所示:
1 | cat >>/opt/tomcat/bin/extraenv.sh <<EOF |
技术背景
LD_PRELOAD 简介
当启动一个动态链接的程序时,它并没有所有需要的函数代码。那么将会发生什么?
- 程序被加载到内存中
- 动态链接器会找出该程序运行所需的其他库(
.so
文件) - 它也会将这些库加载到内存中
- 然后将所有东西连接起来
LD_PRELOAD
是一个系统环境变量,用于在运行程序时强制加载自定义的共享库。它是 Linux 环境中的动态链接功能的一部分,允许在程序运行时动态地影响共享库的加载行为。
当一个程序运行时,它会加载所需的共享库(如标准 C 库 libc
)。LD_PRELOAD
允许在程序加载其正常依赖的共享库之前,优先加载用户指定的共享库。因此,用户可以用自定义的实现替换某些函数或修改程序的行为,而无需更改程序本身的代码。下述为主要的一些使用场景:
a. 函数拦截与重写
通过创建一个共享库,重写某些系统调用或函数的实现(例如
malloc()
、open()
)。在目标程序运行时,强制优先使用自定义实现,从而修改程序行为。
b. 性能调试
拦截内存分配函数(如
malloc
和free
)以检测内存泄漏。记录函数调用和参数,帮助调试程序运行。
c. 兼容性修复
如果运行的程序依赖某些过时的库或函数,可以通过
LD_PRELOAD
动态提供兼容实现,而不需要更改系统环境。d. 时间伪造
像
faketime
这样的工具使用LD_PRELOAD
注入库,从而伪造程序感知到的系统时间。e. 安全性测试
拦截和检查文件访问、网络调用等敏感操作,模拟安全攻击场景或保护特定资源。
使用方式
1 | LD_PRELOAD=/PATH/DEST.so <command> |
下述为三个主要场景示例:
a. 拦截并修改系统调用
假设我们有一个自定义库 myopen.so
,重写了 open()
函数以记录文件访问:
1 |
|
编译为共享库:
1 | gcc -shared -fPIC -o myopen.so myopen.c -ldl |
使用 LD_PRELOAD
加载:
1 | LD_PRELOAD=./myopen.so ls |
输出将记录所有文件访问。
b. 模拟内存分配问题
使用 libmalloc.so
来检测内存分配函数(如 malloc
和 free
的调用次数):
1 | LD_PRELOAD=/usr/lib/libmalloc.so my_program |
c. 修复兼容性问题
如果程序需要一个旧版本的 libc.so
,可以使用:
1 | LD_PRELOAD=/path/to/old_libc.so my_program |
在使用LD_PRELOAD
,需要注意以下几点:
a. 优先级
LD_PRELOAD
的库会优先加载并覆盖系统默认的库,但仅对动态链接的程序生效。静态链接的程序不会被影响。
b. 权限限制
- 出于安全原因,
LD_PRELOAD
通常被忽略在setuid
或setgid
程序中,以防止恶意注入。
c. 影响范围
- 仅影响当前终端会话或明确使用
LD_PRELOAD
的进程,不会改变全局环境。
d. 调试复杂性
- 在覆盖核心系统函数时,使用
LD_PRELOAD
可能引入意外行为。
faketime简介
libfaketime
是一个与 faketime
工具配套的共享库,通过 LD_PRELOAD
环境变量,在程序载入时优先加载 libfaketime.so.1
共享库。它通过特定虚假时间的逻辑代替 libc
原生提供的时间函数逻辑,实现了为程序指定绝对日期或相对日期的能力,而不影响操作系统的全局时间。
- faketime 设置方式
libfaketime 接受五种提供 faketime 的方式,包括:
a. 通过设置环境变量 FAKETIME
b. 通过由环境变量 FAKETIME_TIMESTAMP_FILE
声明的文件
c. 通过家目录下的 .faketimerc
文件
d. 通过系统级别的 /etc/faketimerc
文件
e. 通过设置环境变量FAKETIME_UPDATE_TIMESTAMP_FILE
并执行命令 date -s ""
使用 b/d/d 方式,可以按照语法修改文件内容。由:
环境变量
FAKETIME_CACHE_DURATION
确定的缓存时间,实现 faketime 的热更新或环境变量
FAKETIME_NO_CACHE=1
放弃缓存,实现 faketime 从文件的实时获取或未配置环境变量,使用默认缓存时间 10 秒
- 工作原理
libfaketime
拦截常见的时间系统调用,例如:
time()
gettimeofday()
clock_gettime()
通过注入自己的实现,它会返回伪造的时间值,而不是实际的系统时间。这种方式只对通过动态链接加载的程序有效,静态链接的程序不受影响。faketime有以下几点特性:
a. 固定时间
让程序始终感知为某个特定时间点,例如模拟 2025 年 1 月 1 日。
b. 时间偏移
以当前时间为基准,增加或减少一定的时间偏移量,例如提前一天或推迟一小时。
c. 加速或减速时间
模拟时间流逝的速度变化,例如每秒模拟为两秒(时间加速),或延缓时间流逝速度(时间减速)。
d. 动态时间调整
支持通过文件或环境变量动态调整伪造时间的规则,灵活应对测试需求。
安装与使用
libfaketime
通常可以通过系统的包管理器安装:
在 Debian系:
1
sudo apt install libfaketime
在 RHEL系:
1
sudo yum install libfaketime
通过设置 LD_PRELOAD
,将 libfaketime
注入目标程序:
1 | LD_PRELOAD=/usr/lib/libfaketime.so.1 FAKETIME="<伪造时间>" <命令> |
主要有以下几种场景:
a. 固定时间点
让程序感知到固定时间,例如 2025 年 1 月 1 日:
1 | LD_PRELOAD=/usr/lib/libfaketime.so.1 FAKETIME="2025-01-01 00:00:00" date |
输出结果:
1 | Wed Jan 1 00:00:00 UTC 2025 |
b. 时间偏移
将时间向前或向后偏移 1 天:
1 | LD_PRELOAD=/usr/lib/libfaketime.so.1 FAKETIME="+1d" date |
或:
1 | LD_PRELOAD=/usr/lib/libfaketime.so.1 FAKETIME="-1d" date |
c. 时间加速
模拟时间加速,让程序运行时间每秒等效于两秒:
1 | LD_PRELOAD=/usr/lib/libfaketime.so.1 FAKETIME="@2x" sleep 5 |
本应需要 5 秒的任务,现在可能只需 2.5 秒完成。
d. 动态调整时间
使用文件配置时间伪造规则:
1 | LD_PRELOAD=/usr/lib/libfaketime.so.1 FAKETIME="@" ./my_program |
通过配置文件(如 /etc/faketimerc
)动态调整时间规则。
使用faketime需要注意以下几点:
a. 仅影响动态链接程序
静态链接的程序直接使用系统调用,不会被 libfaketime
拦截,比如Golang
b. 对多线程程序的影响
多线程程序可能对时间操作敏感,使用 libfaketime
时需要注意可能引发的并发问题。
c. 环境隔离
使用 LD_PRELOAD
仅影响当前终端或进程,不会对全局环境产生影响。
d. 安全问题
出于安全考虑,某些敏感程序可能会忽略 LD_PRELOAD
(如 setuid
程序)。
寻根溯源
根据issue的说明,需要针对特定JDK版本,移除变量DONT_FAKE_MONOTONIC
- 定位JVM时钟
java -Xlog:all=info
是 Java 的一个命令行选项,用于控制 JVM 的日志输出行为, 在排查过程中使用该配置,打印关键信息(连半路出家都算不上)。
1 | LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1 FAKETIME="@2024-12-22 19:44:32" java -Xlog:all=info Main.java |
可以发现JDK 21底层JVM判断可以使用CLOCK_MONOTONIC时钟是通过pthread_condattr_setclock判断,当 JVM 使用条件变量(如 pthread_cond_timedwait
)实现超时等待时,可以选择使用单调时钟(CLOCK_MONOTONIC
)来避免系统时间调整对超时行为的影响。
2. 排查阻塞点
通过下述信息可以发现,Thread.Sleep行为调用链以及阻塞点
1 | Thread 2 (Thread 0x7fb00eafa700 (LWP 15984)): |
下述为详细DEBUG过程
执行gdb命令,attach java进程
1
gdb -p 15959
堆栈回溯
1 | (gdb) bt |
列出当前所有线程信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27(gdb) info threads
Id Target Id Frame
25 Thread 0x7fb089023700 (LWP 15960) "java" 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
24 Thread 0x7fb08553c700 (LWP 15962) "GC Thread#0" 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
23 Thread 0x7fb08543b700 (LWP 15963) "G1 Main Marker" 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
22 Thread 0x7fb08533a700 (LWP 15964) "G1 Conc#0" 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
21 Thread 0x7fb084a31700 (LWP 15965) "G1 Refine#0" 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
20 Thread 0x7fb084930700 (LWP 15966) "G1 Service" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
19 Thread 0x7fb084753700 (LWP 15967) "VM Periodic Tas" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
18 Thread 0x7fb084652700 (LWP 15968) "VM Thread" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
17 Thread 0x7fb0843c8700 (LWP 15969) "Reference Handl" 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
16 Thread 0x7fb0842c7700 (LWP 15970) "Finalizer" 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
15 Thread 0x7fb0841c6700 (LWP 15971) "Signal Dispatch" 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
14 Thread 0x7fb0648af700 (LWP 15972) "Service Thread" 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
13 Thread 0x7fb0647ae700 (LWP 15973) "Monitor Deflati" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
12 Thread 0x7fb0646ad700 (LWP 15974) "C2 CompilerThre" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
11 Thread 0x7fb0645ac700 (LWP 15975) "C1 CompilerThre" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
10 Thread 0x7fb0643db700 (LWP 15976) "Common-Cleaner" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
9 Thread 0x7fb0642da700 (LWP 15977) "Notification Th" 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
8 Thread 0x7fb0641d9700 (LWP 15978) "C2 CompilerThre" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
7 Thread 0x7fb00efff700 (LWP 15979) "C2 CompilerThre" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
6 Thread 0x7fb00eefe700 (LWP 15980) "GC Thread#1" 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
5 Thread 0x7fb00edfd700 (LWP 15981) "GC Thread#2" 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
4 Thread 0x7fb00ecfc700 (LWP 15982) "GC Thread#3" 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
3 Thread 0x7fb00ebfb700 (LWP 15983) "Thread-0" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
2 Thread 0x7fb00eafa700 (LWP 15984) "Thread-1" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
* 1 Thread 0x7fb089024740 (LWP 15959) "java" 0x00007fb088a08017 in pthread_join () from /lib64/libpthread.so.0其中关键信息
1
2
33 Thread 0x7fb00ebfb700 (LWP 15983) "Thread-0" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
2 Thread 0x7fb00eafa700 (LWP 15984) "Thread-1" 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0显示所有线程的堆栈回溯
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300(gdb) thread apply all bt
Thread 25 (Thread 0x7fb089023700 (LWP 15960)):
#0 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb0876be95b in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#2 0x00007fb0876663ec in Monitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0879361ea in Threads::destroy_vm() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb087355fa2 in jni_DestroyJavaVM () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb089035942 in JavaMain () from /usr/java/jdk21/bin/../lib/libjli.so
#6 0x00007fb089039289 in ThreadJavaMain () from /usr/java/jdk21/bin/../lib/libjli.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 24 (Thread 0x7fb08553c700 (LWP 15962)):
#0 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
#1 0x00007fb088a0cbcf in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2 0x00007fb088a0cc6b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3 0x00007fb08776afa2 in PosixSemaphore::wait() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0879e4d5b in WorkerThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 23 (Thread 0x7fb08543b700 (LWP 15963)):
#0 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb0876be95b in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#2 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb08718e80a in G1ConcurrentMarkThread::wait_for_next_cycle() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb08718fa29 in G1ConcurrentMarkThread::run_service() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0870453fb in ConcurrentGCThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#9 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 22 (Thread 0x7fb08533a700 (LWP 15964)):
#0 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
#1 0x00007fb088a0cbcf in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2 0x00007fb088a0cc6b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3 0x00007fb08776afa2 in PosixSemaphore::wait() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0879e4d5b in WorkerThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
---Type <return> to continue, or q <return> to quit---
Thread 21 (Thread 0x7fb084a31700 (LWP 15965)):
#0 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb0876be95b in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#2 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb087195d7c in G1PrimaryConcurrentRefineThread::wait_for_completed_buffers() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0871960f8 in G1ConcurrentRefineThread::run_service() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0870453fb in ConcurrentGCThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#9 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 20 (Thread 0x7fb084930700 (LWP 15966)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb08010b1c0, mutex=0x7fb08010b198, abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0871eac11 in G1ServiceThread::wait_for_task() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0871eafa0 in G1ServiceThread::run_service() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0870453fb in ConcurrentGCThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#9 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 19 (Thread 0x7fb084753700 (LWP 15967)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb087eefcd0 <mutex_init()::PeriodicTask_lock_storage+48>, mutex=0x7fb087eefca8 <mutex_init()::PeriodicTask_lock_storage+8>,
abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb08767ed4d in WatcherThread::sleep() const () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb08767ee51 in WatcherThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#9 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 18 (Thread 0x7fb084652700 (LWP 15968)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb087eeead0 <mutex_init()::VMOperation_lock_storage+48>, mutex=0x7fb087eeeaa8 <mutex_init()::VMOperation_lock_storage+8>,
abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0879be7f5 in VMThread::wait_for_operation() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879bf318 in VMThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
---Type <return> to continue, or q <return> to quit---
#6 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#9 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 17 (Thread 0x7fb0843c8700 (LWP 15969)):
#0 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb0876be95b in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#2 0x00007fb0876663ec in Monitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb08739937a in JVM_WaitForReferencePendingList () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb06fdf39c0 in ?? ()
#5 0x0000000000000004 in ?? ()
#6 0x00007fb0843c7948 in ?? ()
#7 0x0000000000000000 in ?? ()
Thread 16 (Thread 0x7fb0842c7700 (LWP 15970)):
#0 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb0876be0ab in PlatformEvent::park() () from /usr/java/jdk21/lib/server/libjvm.so
#2 0x00007fb08768e3f5 in ObjectMonitor::wait(long, bool, JavaThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0878da904 in ObjectSynchronizer::wait(Handle, long, JavaThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb08739ad7f in JVM_MonitorWait () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb06fdf39c0 in ?? ()
#6 0x00007fb0842c67a8 in ?? ()
#7 0x00007fb06fdf3697 in ?? ()
#8 0x0000000000000000 in ?? ()
Thread 15 (Thread 0x7fb0841c6700 (LWP 15971)):
#0 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
#1 0x00007fb088a0cbcf in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2 0x00007fb088a0cc6b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3 0x00007fb08776afa2 in PosixSemaphore::wait() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb08781b93f in os::signal_wait() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0876a59e5 in signal_thread_entry(JavaThread*, JavaThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#9 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 14 (Thread 0x7fb0648af700 (LWP 15972)):
#0 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb0876be95b in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#2 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb08776ca82 in ServiceThread::service_thread_entry(JavaThread*, JavaThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
---Type <return> to continue, or q <return> to quit---
#6 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 13 (Thread 0x7fb0647ae700 (LWP 15973)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb087ef0cd0 <mutex_init()::MonitorDeflation_lock_storage+48>, mutex=0x7fb087ef0ca8 <mutex_init()::MonitorDeflation_lock_storage+8>,
abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb087659353 in MonitorDeflationThread::monitor_deflation_thread_entry(JavaThread*, JavaThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#9 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 12 (Thread 0x7fb0646ad700 (LWP 15974)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb087ef0250 <mutex_init()::MethodCompileQueue_lock_storage+48>, mutex=0x7fb087ef0228 <mutex_init()::MethodCompileQueue_lock_storage+8>,
abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0876663ec in Monitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb087026e76 in CompileQueue::get(CompilerThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb08702ae79 in CompileBroker::compiler_thread_loop() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#9 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 11 (Thread 0x7fb0645ac700 (LWP 15975)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb087ef0250 <mutex_init()::MethodCompileQueue_lock_storage+48>, mutex=0x7fb087ef0228 <mutex_init()::MethodCompileQueue_lock_storage+8>,
abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0876663ec in Monitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb087026e76 in CompileQueue::get(CompilerThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb08702ae79 in CompileBroker::compiler_thread_loop() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#9 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 10 (Thread 0x7fb0643db700 (LWP 15976)):
---Type <return> to continue, or q <return> to quit---
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb08017cab8, mutex=0x7fb08017ca90, abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be547 in Parker::park(bool, long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0879603c4 in Unsafe_Park () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb06fdf39c0 in ?? ()
#5 0x00007fb0643da578 in ?? ()
#6 0x00007fb0643da5e8 in ?? ()
#7 0x00007fb06fdef180 in ?? ()
#8 0x00000000868003f8 in ?? ()
#9 0x00007fb0643da580 in ?? ()
#10 0x0000000000000000 in ?? ()
Thread 9 (Thread 0x7fb0642da700 (LWP 15977)):
#0 0x00007fb088a0aa35 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb0876be95b in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#2 0x00007fb087666369 in Monitor::wait_without_safepoint_check(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb08767f2f2 in NotificationThread::notification_thread_entry(JavaThread*, JavaThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 8 (Thread 0x7fb0641d9700 (LWP 15978)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb087ef0250 <mutex_init()::MethodCompileQueue_lock_storage+48>, mutex=0x7fb087ef0228 <mutex_init()::MethodCompileQueue_lock_storage+8>,
abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0876663ec in Monitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb087026e76 in CompileQueue::get(CompilerThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb08702ae79 in CompileBroker::compiler_thread_loop() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#9 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 7 (Thread 0x7fb00efff700 (LWP 15979)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb087ef0250 <mutex_init()::MethodCompileQueue_lock_storage+48>, mutex=0x7fb087ef0228 <mutex_init()::MethodCompileQueue_lock_storage+8>,
abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be937 in PlatformMonitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0876663ec in Monitor::wait(unsigned long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb087026e76 in CompileQueue::get(CompilerThread*) () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb08702ae79 in CompileBroker::compiler_thread_loop() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0872d5cd8 in JavaThread::thread_main_inner() () from /usr/java/jdk21/lib/server/libjvm.so
---Type <return> to continue, or q <return> to quit---
#7 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#8 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#9 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#10 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 6 (Thread 0x7fb00eefe700 (LWP 15980)):
#0 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
#1 0x00007fb088a0cbcf in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2 0x00007fb088a0cc6b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3 0x00007fb08776afa2 in PosixSemaphore::wait() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0879e4d5b in WorkerThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 5 (Thread 0x7fb00edfd700 (LWP 15981)):
#0 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
#1 0x00007fb088a0cbcf in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2 0x00007fb088a0cc6b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3 0x00007fb08776afa2 in PosixSemaphore::wait() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0879e4d5b in WorkerThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 4 (Thread 0x7fb00ecfc700 (LWP 15982)):
#0 0x00007fb088a0cb3b in do_futex_wait.constprop.1 () from /lib64/libpthread.so.0
#1 0x00007fb088a0cbcf in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2 0x00007fb088a0cc6b in sem_wait@@GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3 0x00007fb08776afa2 in PosixSemaphore::wait() () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0879e4d5b in WorkerThread::run() () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb0879283b8 in Thread::call_run() () from /usr/java/jdk21/lib/server/libjvm.so
#6 0x00007fb0876b312a in thread_native_entry(Thread*) () from /usr/java/jdk21/lib/server/libjvm.so
#7 0x00007fb088a06ea5 in start_thread () from /lib64/libpthread.so.0
#8 0x00007fb08852bb0d in clone () from /lib64/libc.so.6
Thread 3 (Thread 0x7fb00ebfb700 (LWP 15983)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb08070b250, mutex=0x7fb08070b228, abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be25f in PlatformEvent::park_nanos(long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0872d8d59 in JavaThread::sleep_nanos(long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0873989ed in JVM_Sleep () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb06fdf39c0 in ?? ()
#6 0x0000000000000000 in ?? ()
---Type <return> to continue, or q <return> to quit---
Thread 2 (Thread 0x7fb00eafa700 (LWP 15984)):
#0 0x00007fb088a0ade2 in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1 0x00007fb088c22499 in pthread_cond_timedwait_common (cond=0x7fb0806e7350, mutex=0x7fb0806e7328, abstime=<optimized out>, compat=FT_COMPAT_GLIBC_2_3_2) at libfaketime.c:2840
#2 0x00007fb0876be25f in PlatformEvent::park_nanos(long) () from /usr/java/jdk21/lib/server/libjvm.so
#3 0x00007fb0872d8d59 in JavaThread::sleep_nanos(long) () from /usr/java/jdk21/lib/server/libjvm.so
#4 0x00007fb0873989ed in JVM_Sleep () from /usr/java/jdk21/lib/server/libjvm.so
#5 0x00007fb06fdf39c0 in ?? ()
#6 0x0000000000000000 in ?? ()
Thread 1 (Thread 0x7fb089024740 (LWP 15959)):
#0 0x00007fb088a08017 in pthread_join () from /lib64/libpthread.so.0
#1 0x00007fb089039e6f in CallJavaMainInNewThread () from /usr/java/jdk21/bin/../lib/libjli.so
#2 0x00007fb089036ffd in ContinueInNewThread () from /usr/java/jdk21/bin/../lib/libjli.so
#3 0x00007fb089037a4d in JLI_Launch () from /usr/java/jdk21/bin/../lib/libjli.so
#4 0x000055fa5ded6b0f in main ()- 根因溯源
其中Thread.Sleep在jdk21+9版本下的调用路径:
a. Thread.Sleep https://github.com/openjdk/jdk21u/blob/e45287d1ad9dcadf8a23d3271f1b675b8dade0ac/src/java.base/share/classes/java/lang/Thread.java#L498
b. Thread.Sleep-> sleep0
c. sleep2 对应JNI实现 JVM_Sleep
d. JVM_Sleep中使用jvm实现sleep_nanos https://github.com/openjdk/jdk21u/blob/e45287d1ad9dcadf8a23d3271f1b675b8dade0ac/src/hotspot/share/runtime/javaThread.cpp#L1990C18-L1990C29
e. 其中sleep_nanos内部调用slp->park_nanos(nanos_remaining)
f. park_nanos调用了glibc的pthread_cond_timedwait,但被faketime劫持
- faketime中pthread_cond_timedwait,因clock_id不是MONOTONIC,因此计算用了realtime
- 然后传递至glibc的pthread_cond_timedwait,其调用clock_gettime来做超时判断,这里同样返回的是faketime
- 导致一直等待,jvm的thread无法unpark
其中sleep_nanos 的实现如下所示:
1 | bool JavaThread::sleep_nanos(jlong nanos) { |
其中faktime针对pthread_cond_timedwait在0.9.8与0.9.10均实现了劫持,但关于CLOCK_MONOTONIC
行为应该是存在差异的,其中0.9.10根据Glibc版本做了自适应调整