我将 CLion 与一个 c++ 项目 (cmake) 一起使用,该项目启动一个 jvm。java部分是用gradle构建的。该项目有效,但我在调试时遇到问题。
当我启动 JVM 时,我立即得到一个 SIGSEGV。我知道这是正常的,除了忽略 SIGSEGV 之外没有其他解决方法。有点烦人但还不错,因为每次会话只发生一次。
但是,在那之后,我继续调试,我得到了持续的 SIGBUS 信号。
<unknown> 0x000000011f108385
<unknown> 0x000000011761dca7
<unknown> 0x000000011761dca7
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761da00
<unknown> 0x0000000117614849
JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, Thread*) 0x000000010bf3a582
StackWalk::fetchFirstBatch(BaseFrameStream&, Handle, long, int, int, int, objArrayHandle, Thread*) 0x000000010c227cac
StackWalk::walk(Handle, long, int, int, int, objArrayHandle, Thread*) 0x000000010c2278fc
JVM_CallStackWalk 0x000000010bfb14a2
<unknown> 0x0000000117623950
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x0000000117614849
JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, Thread*) 0x000000010bf3a582
InstanceKlass::call_class_initializer(Thread*) 0x000000010bf22af7
InstanceKlass::initialize_impl(Thread*) 0x000000010bf2244f
Reflection::invoke_constructor(oopDesc*, objArrayHandle, Thread*) 0x000000010c1ebdbb
JVM_NewInstanceFromConstructor 0x000000010bfc14f6
<unknown> 0x0000000117623950
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761dae2
<unknown> 0x000000011761dcec
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761dae2
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x000000011761da00
<unknown> 0x0000000117614849
JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, Thread*) 0x000000010bf3a582
jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*) 0x000000010bf7e2af
jni_CallStaticVoidMethodV 0x000000010bf81c69
JNIEnv_::CallStaticVoidMethod(_jclass*, _jmethodID*, ...) jni.h:1521
main main.cpp:80
start 0x00007fff6f6563d5
start 0x00007fff6f6563d5
它并没有在我的代码中停止。除了忽略所有 SIGBUS 之外,我不明白为什么会发生这种情况,或者是否有可能避免它们。
我最小化了我的代码并创建了最简单的示例来重现该问题。基本上,我创建了一个 cpp 项目,它以org/junit/platform/console/ConsoleLauncher作为主要(junit5)启动一个 jni,这使得一个简单的测试。SIGBUS 发生了。它发生在我的测试甚至运行之前。
我怀疑 JUnit 中的某些东西,但不确定。有什么办法可以找到根本原因?
复制示例项目在这里:https ://github.com/tallavi/sigbus-reproduction
如果我运行它,你可以看到代码在调用 java 部分后停止运行,没有“调用后”,没有“CppMainEnd”:
CppMainStart
current_path: /Users/tal/Development/v2x/qa-automation/sigbus-reproduction/out
Loading JAR: jars/junit-platform-console-standalone-1.5.2.jar
Loading JAR: jars/.DS_Store
Loading JAR: jars/junit-platform-console-standalone-1.6.0-M1.jar
Loading JAR: jars/sigbus-reproduction.jar
CreateVM: JVM loaded successfully!
Before call
test START
test END
Thanks for using JUnit! Support its development at https://junit.org/sponsoring
.
+-- JUnit Jupiter [OK]
| '-- FirstTest [OK]
| '-- myTest() [OK]
'-- JUnit Vintage [OK]
Test run finished after 154 ms
[ 3 containers found ]
[ 0 containers skipped ]
[ 3 containers started ]
[ 0 containers aborted ]
[ 3 containers successful ]
[ 0 containers failed ]
[ 1 tests found ]
[ 0 tests skipped ]
[ 1 tests started ]
[ 0 tests aborted ]
[ 1 tests successful ]
[ 0 tests failed ]
Process finished with exit code 0
如果我只是将 main 从 JUnit5 更改为我的 main 并运行相同的代码,一切正常:
CppMainStart
current_path: /Users/tal/Development/v2x/qa-automation/sigbus-reproduction/out
Loading JAR: jars/junit-platform-console-standalone-1.5.2.jar
Loading JAR: jars/.DS_Store
Loading JAR: jars/junit-platform-console-standalone-1.6.0-M1.jar
Loading JAR: jars/sigbus-reproduction.jar
CreateVM: JVM loaded successfully!
Before call
main START
main END
After call
CppMainEnd
Process finished with exit code 0
我按照@Oo.oO 的建议处理了信号,但它当然不能解决问题。Java 代码完成,但如果我尝试访问该 JVM,例如,销毁它,它就会挂起!:
但是,如果我让它运行(而不是尝试调试它),它会因不同的错误而崩溃:
main(31549,0x1177515c0) malloc: *** error for object 0x7ffee6360628: pointer being freed was not allocated
main(31549,0x1177515c0) malloc: *** set a breakpoint in malloc_error_break to debug
有了这个跟踪:
请注意,SIGBUS 并不总是发生,但 JVM 调用之后的代码 100% 的时间停止运行。
希望这对任何人都有意义..
更新:这是它在 lldb 中的外观:
MyComputer:out tal$ lldb main
(lldb) target create "main"
Current executable set to 'main' (x86_64).
(lldb) r
Process 57274 launched: '/Users/tal/Development/v2x/qa-automation/sigbus-reproduction/out/main' (x86_64)
CppMainStart
Process 57274 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSEGV
frame #0: 0x000000010b33f51b
-> 0x10b33f51b: movl (%rsi), %eax
0x10b33f51d: leaq 0x30(%rbp), %rsi
0x10b33f521: movl $0x10000, %eax ; imm = 0x10000
0x10b33f526: andl 0x4(%rsi), %eax
Target 0: (main) stopped.
(lldb) c
Process 57274 resuming
CreateVM: JVM loaded successfully!
Before call
Process 57274 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGBUS
frame #0: 0x0000000112e263ff
-> 0x112e263ff: testl %eax, (%r10)
0x112e26402: retq
0x112e26403: nop
0x112e26404: nop
Target 0: (main) stopped.
(lldb) c
Process 57274 resuming
test START
test END
Thanks for using JUnit! Support its development at https://junit.org/sponsoring
╷
├─ JUnit Jupiter ✔
│ └─ FirstTest ✔
│ └─ myTest() ✔
└─ JUnit Vintage ✔
Test run finished after 2740 ms
[ 3 containers found ]
[ 0 containers skipped ]
[ 3 containers started ]
[ 0 containers aborted ]
[ 3 containers successful ]
[ 0 containers failed ]
[ 1 tests found ]
[ 0 tests skipped ]
[ 1 tests started ]
[ 0 tests aborted ]
[ 1 tests successful ]
[ 0 tests failed ]
After call
before destroying
after destroying
CppMainEnd
Process 57274 exited with status = 0 (0x00000000)