JNI共享库用Clang UBSan遇__ubsan_vptr_type_cache未定义符号错误
This error usually crops up when the Undefined Behavior Sanitizer (UBSan) runtime isn't properly linked into your JNI shared library. Your executable build works because the linker automatically pulls in UBSan symbols during the final link, but JNI libraries are loaded dynamically by the JVM—so you need to make sure those UBSan symbols are either embedded in the library or resolvable at runtime.
Here’s how to fix it step by step:
1. Make Sure Your Link Command Includes UBSan Flags
Your compile command correctly uses -fsanitize=address,undefined, but your truncated link command is likely missing these critical flags. The -fsanitize flags need to be present in both the compilation and linking phases to tell the linker to include the UBSan runtime.
Update your link command to match the sanitizer flags from your compile step (and add -shared since we’re building a shared library):
ccache clang++ -Qunused-arguments -fcolor-diagnostics -std=c++11 -O1 -g3 -fPIC -fsanitize=address,undefined -fno-omit-frame-pointer -I /usr/lib/jvm/java-8-openjdk-amd64/include -I /usr/lib/jvm/java-8-openjdk-amd64/include/linux -shared -o native/libinstrument.so native/instrument.o
2. Static Link the UBSan Runtime (Recommended for JNI)
To avoid relying on the system’s UBSan library being present and compatible when the JVM loads your JNI library, statically link the UBSan runtime with -static-libubsan (and -static-libasan if you’re using AddressSanitizer too). This embeds the sanitizer runtime directly into your shared library.
Modify your link command to include these static linking flags:
ccache clang++ -Qunused-arguments -fcolor-diagnostics -std=c++11 -O1 -g3 -fPIC -fsanitize=address,undefined -fno-omit-frame-pointer -static-libubsan -static-libasan -I /usr/lib/jvm/java-8-openjdk-amd64/include -I /usr/lib/jvm/java-8-openjdk-amd64/include/linux -shared -o native/libinstrument.so native/instrument.o
3. Verify the Symbol is Present in the Library
After rebuilding, you can confirm the __ubsan_vptr_type_cache symbol is included using nm:
nm -D native/libinstrument.so | grep __ubsan_vptr_type_cache
If the symbol shows up (marked with a T for defined in the text section), the issue should be resolved.
Why This Works
When building an executable, the linker resolves UBSan symbols automatically when -fsanitize is used. For shared libraries though, the linker won’t pull in these symbols unless explicitly instructed—especially since JNI libraries are loaded dynamically. Static linking ensures all necessary UBSan symbols are baked into your library, so the JVM can resolve them without external dependencies.
内容的提问来源于stack exchange,提问作者Pascal Kesseli

