JVM在HLT指令上发生SIGSEGV崩溃?

3

OpenJDK 11.0.19似乎存在一个错误,有时会导致java.util.GregorianCalendar.computeTime()崩溃。

最终更新:感谢@apangin,我发现Linux发送的是SIGSEGV而不是我预期的SIGILL。请参见函数http://elixir.free-electrons.com/linux/v4.9/source/arch/x86/kernel/traps.c#L487的最后一行。

更新:回到OpenJDK 11.0.18后,问题消失了。无论如何,我想了解HLT指令如何导致分段错误。

Red Hat Enterprise Linux release 8.7 (Ootpa) 4.18.0-425.19.2.el8_7.x86_64

# JRE version: OpenJDK Runtime Environment (Red_Hat-11.0.19.0.7-1.el8_7) (11.0.19+7) (build 11.0.19+7-LTS)
# Java VM: OpenJDK 64-Bit Server VM (Red_Hat-11.0.19.0.7-1.el8_7) (11.0.19+7-LTS, mixed mode, sharing, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# J 7581 c2 java.util.GregorianCalendar.computeTime()V java.base@11.0.19 (970 bytes) @ 0x00007ff72826feeb [0x00007ff72826f440+0x0000000000000aab]

Stack: [0x00007ff73ec47000,0x00007ff73ed48000],  sp=0x00007ff73ed44ad0,  free space=1014k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
J 7581 c2 java.util.GregorianCalendar.computeTime()V java.base@11.0.19 (970 bytes) @ 0x00007ff72826feeb [0x00007ff72826f440+0x0000000000000aab]

siginfo: si_signo: 11 (SIGSEGV), si_code: 128 (SI_KERNEL), si_addr: 0x0000000000000000

Registers:
RAX=0x0000000000000000, RBX=0x00000000e5b5f858, RCX=0x0000000000000000, RDX=0x0000000000000000
RSP=0x00007ff73ed44ad0, RBP=0x0000000000000000, RSI=0x00007ff73ed441d1, RDI=0x00007ff738023820
R8 =0x0000000000000000, R9 =0x00007ff73ed44150, R10=0x00000000000007cf, R11=0x0000000000000000
R12=0x0000000000000000, R13=0x0000000000001896, R14=0x00007ff6cda239e0, R15=0x00007ff738028800
RIP=0x00007ff72826feeb, EFLAGS=0x0000000000010246, CSGSFS=0x002b000000000033, ERR=0x0000000000000000
  TRAPNO=0x000000000000000d

Instructions: (pc=0x00007ff72826feeb)
...
0x00007ff72826febb:   08 4c 8b 6c 24 18 4c 8b c0 e9 a1 f7 ff ff be 7e
0x00007ff72826fecb:   ff ff ff 48 8b 6c 24 08 e8 28 1f 1a f8 48 bf 98
0x00007ff72826fedb:   4b bd 3d f7 7f 00 00 48 83 e4 f0 e8 25 e0 48 15
0x00007ff72826feeb:   f4 be f4 ff ff ff 48 89 1c 24 48 89 44 24 f8 8b
0x00007ff72826fefb:   44 24 10 89 44 24 08 48 8b 44 24 f8 4c 89 6c 24
0x00007ff72826ff0b:   10 66 66 90 e8 ec 1e 1a f8 be e4 ff ff ff 48 8b
0x00007ff72826ff1b:   6c 24 08 44 89 54 24 04 e8 d8 1e 1a f8 be e4 ff
0x00007ff72826ff2b:   ff ff 49 8b eb 89 5c 24 04 66 66 90 e8 c4 1e 1a
...

PC/RIP指向一个包含HLT指令(0xF4)的地址:

e8 28 1f 1a f8          call   0xfffffffff81a1f45
48 bf 98 4b bd 3d f7    movabs rdi,0x7ff73dbd4b98
7f 00 00
48 83 e4 f0             and    rsp,0xfffffffffffffff0
e8 25 e0 48 15          call   0x1548e055
f4                      hlt
be f4 ff ff ff          mov    esi,0xfffffff4
48 89 1c 24             mov    QWORD PTR [rsp],rbx
48 89 44 24 f8          mov    QWORD PTR [rsp-0x8],rax

HLT指令如何触发分段错误?

我花了几个小时搜索类似的内容,但没有找到任何东西。


1
@andrewJames:遗憾的是,只有整个应用程序运行时才会发生崩溃。当我通过一个单独的测试应用程序以无限循环调用相关方法时,崩溃从未发生过。 - kingofworms
1
@andrewJames:我们回到了OpenJDK 11.0.18,一切都按预期工作。不过,了解HLT如何触发分段错误会很有帮助。 - kingofworms
1
我在Rocky Linux 8上遇到了同样的问题(这是RHEL 8的克隆版):使用java-11-openjdk-headless-11.0.19.0.7-1.el8_7.x86_64会导致崩溃,而使用更新前直接版本为java-11-openjdk-headless-11.0.18.0.10-2.el8_7.x86_64则可以正常工作。该问题必须是由此git提交引入的。 - rsc
OpenJDK问题:https://bugs.openjdk.org/browse/JDK-8307978 - Robert Hume
1个回答

0

HLT 是一条特权指令。在用户模式下执行时,会触发通用保护故障。在 Linux 中,这将导致 SIGSEGV 被发送到有问题的进程。

HotSpot JVM 仅在从未预期发生的情况下在动态生成的代码中发出 HLT 指令。因此,显然存在 JVM 错误。使用 -XX:+ShowMessageBoxOnError 重新运行 JVM,以获取有关特定断言失败的更多信息。


谢谢,这就是我要找的信息。你有没有想法为什么编译器会在这个位置放置HLT?我知道它用HLT来填充,但它似乎不是两个函数之间的间隙。 - kingofworms
@kingofworms 这是在生成的代码中的一种断言。 - apangin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接