Java JNI调用C语言计算BMI输出NaN该如何修复
问题根因
NaN输出的核心问题出在C代码的字段读取逻辑错误:
- Java代码中
weight和height的声明类型是double,你在C代码中已经通过GetDoubleField正确读取到了两个字段的值,却又额外调用了GetIntField再次读取同一字段。GetIntField会把存储double类型的内存空间按int格式强制解析,得到的是完全错误的垃圾值,绝大多数情况下会得到height1 = 0,后续计算weight1 / (0 * 0)就会产生NaN。
修复方案
直接删除C代码中两行错误的GetIntField调用即可,修复后的C代码如下:
#include <jni.h> #include <math.h> JNIEXPORT jdouble JNICALL Java_BMICalculator_BMIcalculate(JNIEnv *env, jobject obj){ jdouble total, weight1, height1 ; jfieldID fid1, fid2; jclass cls = (*env)->GetObjectClass(env,obj); fid1 = (*env)->GetFieldID(env,cls,"weight","D"); fid2 = (*env)->GetFieldID(env,cls,"height","D"); if((fid1 == NULL) || (fid2 == NULL)) return 0; weight1 = (*env)->GetDoubleField(env,obj,fid1); height1 = (*env)->GetDoubleField(env,obj,fid2); // 已删除错误的GetIntField调用 height1 = height1 / 100; total = weight1 / ( height1 * height1 ); return total; }
额外注意事项
- 编译动态库时要保证链接了JDK的jni头文件路径,比如Linux下编译命令参考:
gcc -shared -fPIC -I$JAVA_HOME/include -I$JAVA_HOME/include/linux Calculate.c -o libCalculate.so - 运行Java代码时要添加JVM参数指定动态库路径:
java -Djava.library.path=. BMICalculator - 动态库命名要符合平台规则:Windows下为
Calculate.dll,Linux下为libCalculate.so,MacOS下为libCalculate.jnilib
内容的提问来源于stack exchange,提问作者TAI YU ZHE
相关产品推荐
相关产品推荐

