HP fortify Unsafe JNI.

本文介绍在Java中使用Apache Commons Lang库替代标准库方法的技巧,包括获取对象类、获取当前时间毫秒数、类型赋值检查、对象哈希码计算、获取类修饰符等,提供更稳定和丰富的功能。

//1. For Object.getClass()
使用apache中API替代.
/**
     * replace Object.getClass().
     * @param obj
     * @return
     * @throws ClassNotFoundException
     */
    public static Class<?> getClassForObject(Object obj){
        Class<?> clazz = null;
        if (obj == null) {
            throw new NullPointerException();
        }
        try {
            clazz = ClassUtils.getClass(ClassUtils.getName(obj));//org.apache.commons.lang3.ClassUtils;
        } catch (ClassNotFoundException e) {
            ValidationUtils.myLoggerError(LOGGER, e.getMessage(),e);
        }
        return clazz;
    }

//2. For System.currentTimeMillis()
    public static long getCurrentTimeMillis() {
        return Instant.now().toEpochMilli();
    }

// 3. For public native boolean isAssignableFrom(Class<?> cls);
    /**
     * Checks if one {@code Class} can be assigned to a variable of
     * another {@code Class}.</p>
     * @param cls: the Class to check, may be null
     * @param tocls: the Class to try to assign into, returns false if null
     * @return
     */
    public static boolean isAssignableFromForCC( Class<?> cls,  Class<?> tocls) {
        return ClassUtils.isAssignable(cls, tocls);// use org.apache.commons.lang3.ClassUtils;
    }

//4. For obj.hashCode()
    public static int hashCodeForCC(Object obj) {
        return ObjectUtils.hashCode(obj);//org.apache.commons.lang3.ObjectUtils;
    }

//5. For getModifiers()
    public static int getModifiersForCC(Class clazz) {
        return ReflectUtils.getClassInfo(clazz).getModifiers();//org.springframework.cglib.core.ReflectUtils;
    }

//6. For public native boolean isInstance(Object obj);we can use keyword instanceof replace it.

//7. For Thread.sleep(5000L);
  TimeUnit.SECONDS.sleep(5);

//8.Thread.currentThread().getContextClassLoader()
  Class.getClassLoader();

FAILED: lib/libInspireFace.so cmd.exe /C "cd . && D:\android\Android\Sdk\ndk\25.2.9519653\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android21 --sysroot=D:/android/Android/Sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -g0 -std=c++14 -O3 -O3 -mfpu=neon -O3 -DNDEBUG -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,--gc-sections -shared -Wl,-soname,libInspireFace.so -o lib\libInspireFace.so @CMakeFiles\InspireFace.rsp && cd ." ld: error: undefined symbol: HFLaunchInspireFace >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GlobalLaunch) ld: error: undefined symbol: HFTerminateInspireFace >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GlobalTerminate) ld: error: undefined symbol: HFQueryInspireFaceLaunchStatus >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_QueryLaunchStatus) ld: error: undefined symbol: HFCreateInspireFaceSession >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_CreateSession) ld: error: undefined symbol: HFReleaseInspireFaceSession >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_ReleaseSession) ld: error: undefined symbol: HFCreateImageStream >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_CreateImageStreamFromBitmap) >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_CreateImageStreamFromByteBuffer) ld: error: undefined symbol: HFDeBugImageStreamDecodeSave >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_WriteImageStreamToFile) ld: error: undefined symbol: HFReleaseImageStream >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_ReleaseImageStream) ld: error: undefined symbol: HFExecuteFaceTrack >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_ExecuteFaceTrack) ld: error: undefined symbol: HFGetNumOfFaceDenseLandmark >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GetFaceDenseLandmarkFromFaceToken) ld: error: undefined symbol: HFGetFaceDenseLandmarkFromFaceToken >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GetFaceDenseLandmarkFromFaceToken) ld: error: undefined symbol: HFFaceFeatureExtract >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_ExtractFaceFeature) ld: error: undefined symbol: HFFaceGetFaceAlignmentImage >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GetFaceAlignmentImage) ld: error: undefined symbol: HFImageBitmapGetData >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GetFaceAlignmentImage) ld: error: undefined symbol: HFReleaseImageBitmap >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GetFaceAlignmentImage) >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_GetFaceAlignmentImage) ld: error: undefined symbol: HFSessionSetTrackPreviewSize >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_SetTrackPreviewSize) ld: error: undefined symbol: HFSessionSetFilterMinimumFacePixelSize >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_SetFilterMinimumFacePixelSize) ld: error: undefined symbol: HFSessionSetFaceDetectThreshold >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_SetFaceDetectThreshold) ld: error: undefined symbol: HFSessionSetTrackModeSmoothRatio >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_SetTrackModeSmoothRatio) ld: error: undefined symbol: HFSessionSetTrackModeNumSmoothCacheFrame >>> referenced by inspireface_jni.cpp >>> cpp/inspireface/CMakeFiles/InspireFace.dir/platform/jni/android/inspireface_jni.cpp.o:(Java_com_insightface_sdk_inspireface_InspireFace_SetTrackModeNumSmoothCacheFrame) ld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors) clang++: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed. Build-AndroidArch : Ninja 编译失败! 所在位置 D:\insightface-master\insightface-master\cpp-package\inspireface\command\build_android.ps1:247 字符: 1 + Build-AndroidArch "arm64-v8a" 21 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Build-AndroidArch
最新发布
08-10
<think>我们正在处理一个Android NDK编译问题,具体是在JNI链接阶段出现了未定义符号的错误。用户提供了三个引用,但引用内容似乎与问题关联不大,可能是误贴或是其他上下文。我们需要专注于用户的问题描述:链接阶段出现未定义符号错误。 常见的未定义符号错误通常由以下原因引起: 1. 缺少链接库:在Android.mk或CMakeLists.txt中没有正确链接所需的库。 2. 函数声明与实现不一致:例如,C++函数名修饰(name mangling)问题,通常发生在C++代码中使用了C语言链接方式(extern "C")不一致的情况。 3. 目标平台不匹配:编译时针对的CPU架构(如armeabi-v7a, arm64-v8a)与链接的库不匹配。 4. 库的依赖顺序问题:链接器在链接库时,库的顺序很重要,因为链接器是按顺序解析符号的。 根据用户提供的错误信息片段(虽然不完整,但我们可以推断): 引用[2]:`D:/Librairies/OpenCV-android-sdk_340/sdk/native/jni/include\opencv2/core/persistence.hpp:1264: error: undefined reference to 'cv::read(cv::FileNode const&, std::__ndk1::vector<:keypoint std::__ndk1::allocator> >&)'` 引用[3]:`jni/gnutls-3.0.12/lib/gnutls_int.h:361: error: expected specifier-qualifier-list before 'gnutls_pk_params_st'` 第一个错误是链接错误(undefined reference),说明在链接时找不到`cv::read`函数的实现。这个函数属于OpenCV库,所以可能是OpenCV库没有正确链接。 第二个错误是编译错误(expected specifier-qualifier-list),通常发生在头文件中,可能是由于头文件包含顺序、宏定义冲突或者缺少前置声明等。 由于用户的问题集中在链接阶段,我们主要关注第一个错误。 解决步骤: 1. **确认OpenCV库的链接**:在Android.mk或CMakeLists.txt中,需要确保正确引用了OpenCV库。 例如,在Android.mk中: ``` LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := my_jni_lib LOCAL_SRC_FILES := my_jni_code.cpp # 添加OpenCV依赖 LOCAL_LDLIBS += -L$(PATH_TO_OPENCV_LIBS)/$(TARGET_ARCH_ABI) -lopencv_java3 include $(BUILD_SHARED_LIBRARY) ``` 注意:`PATH_TO_OPENCV_LIBS`需要替换为OpenCV库的实际路径,并且`TARGET_ARCH_ABI`需要与目标架构匹配。 2. **使用CMake的情况**:在CMakeLists.txt中,确保使用`find_package`或直接链接OpenCV库。 ```cmake cmake_minimum_required(VERSION 3.4.1) find_package(OpenCV REQUIRED) add_library(my_jni_lib SHARED my_jni_code.cpp) target_link_libraries(my_jni_lib ${OpenCV_LIBRARIES}) ``` 3. **检查函数签名**:确保在代码中调用的函数与库中提供的函数一致。特别是C++标准库的版本(如`std::vector`)可能在不同编译环境下有差异。但OpenCV库通常使用`std`命名空间,所以这里很可能是缺少链接库。 4. **关于第二个错误(gnutls_int.h)**:这个错误发生在编译阶段,可能是由于头文件依赖问题。检查是否在包含`gnutls_int.h`之前包含了必要的头文件,或者检查该头文件是否完整。另外,检查是否定义了必要的宏。 5. **检查NDK版本和兼容性**:不同版本的NDK对C++库的支持不同,特别是从NDK r18开始移除了GCC,全面使用Clang,并且STL库也有变化。确保所有依赖库都是用相同或兼容的NDK版本编译。 6. **清理和重新构建**:有时候构建缓存可能导致问题,尝试清理项目并重新构建。 7. **查看详细日志**:使用`ndk-build V=1`(Android.mk)或增加CMake的日志级别,以获取更详细的编译和链接命令,从而检查链接器命令中是否包含了必要的库。 8. **注意库的顺序**:链接器在解析符号时,如果库A依赖于库B,那么库A应该出现在库B之前。在CMake中,`target_link_libraries`会自动处理依赖顺序,但在Android.mk中需要手动调整。 由于用户的具体环境(如使用的构建系统、NDK版本、OpenCV版本等)没有提供,我们只能给出一般性建议。 如果问题仍然存在,请提供以下信息: - 构建系统(Android.mk还是CMake?) - NDK版本 - OpenCV版本 - 目标架构(ABI) - 完整的错误日志 这样我们可以更精确地定位问题。 相关问题: 1. 如何解决Android NDK中“undefined reference to”错误? 2. Android NDK中如何正确链接第三方库(如OpenCV)? 3. 如何升级NDK版本并保持与现有项目的兼容性? 4. 如何解决头文件编译错误(如expected specifier-qualifier-list)? 5. 如何查看NDK编译的详细日志?</think>### Android NDK JNI链接阶段未定义符号错误解决方案 在Android NDK编译过程中,JNI链接阶段出现未定义符号错误通常由以下原因引起: #### 1. **库依赖缺失**(最常见原因) 错误示例:`undefined reference to 'cv::read(...)'`[^2] - **解决方案**: - 在`Android.mk`中显式添加所有依赖库: ```makefile LOCAL_LDLIBS := -llog -lz LOCAL_SHARED_LIBRARIES := opencv_java3 # OpenCV库示例 ``` - 在`CMakeLists.txt`中确保完整链接: ```cmake target_link_libraries( native-lib opencv_java3 # 添加缺失的OpenCV模块 log ) ``` #### 2. **C/C++混编问题** - **场景**:C++代码调用C库时缺少`extern "C"`声明 - **解决方案**: ```cpp // 在头文件中添加 #ifdef __cplusplus extern "C" { #endif void native_function(); // C函数声明 #ifdef __cplusplus } #endif ``` #### 3. **ABI兼容性问题** 错误特征:`gnutls_pk_params_st`等结构体未定义[^3] - **检查项**: - 确保所有第三方库(如OpenCV)与目标ABI(armeabi-v7a/arm64-v8a)匹配 - 验证NDK版本一致性(建议使用NDK r20+) #### 4. **构建系统配置错误** - **关键步骤**: ```gradle // app/build.gradle android { defaultConfig { externalNativeBuild { cmake { arguments "-DANDROID_STL=c++_shared" // 使用动态STL cppFlags "-frtti -fexceptions" } } ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' } // 明确指定ABI } } ``` #### 5. **符号可见性问题** - **解决方案**: - 在`Android.mk`中添加: ```makefile LOCAL_CFLAGS += -fvisibility=hidden LOCAL_CPPFLAGS += -fvisibility=hidden ``` - 显式导出JNI函数: ```cpp __attribute__ ((visibility ("default"))) JNIEXPORT void JNICALL Java_com_example_NativeFunc(JNIEnv*, jobject); ``` #### 调试建议: 1. 使用`nm`工具检查符号是否存在: ```bash $NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android-nm -D libopencv_java3.so | grep cv::read ``` 2. 检查链接顺序:依赖库应放在被依赖库**之后** 3. 清理构建缓存: ```bash ./gradlew clean && ./gradlew --stop ``` > 提示:OpenCV相关错误通常需要链接`opencv_core`/`opencv_imgproc`等具体模块,而非仅`opencv_java3`[^2]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值