android-ndk - android art runtime check_jni.cc 包名错误

标签 android-ndk java-native-interface android-5.0-lollipop

--编辑-- 由于模棱两可的 build.gradle...

./src/main/jniLibs/armeabi-v7a/libaudioboo-native.so
rob@ app$ rm ./src/main/libs/armeabi-v7a/libaudioboo-native.so
rob@ app$ rm ./src/main/obj/local/armeabi-v7a/libaudioboo-native.so
rob@ app$ rm ./src/main/jniLibs/armeabi-v7a/libaudioboo-native.so 

已解决的问题 - 将构建更改为以下内容以仅使用 ./src/main/libs 中的共享库

sourceSets {
    main {
        jni.srcDirs = [] /*disable automatic ndk-build call */
        jniLibs.srcDir 'src/main/libs'
    }
}

在 android5 上坏了,所以我通过为 Android-studio (1.0) ndk 构建调整它来使用它。正如答案@holo 所指出的,我扫描了所有“findClass”的代码。注意 - 将第 34 行的字符串常量从

更改为
 "fm.audioboo.jni.FLACStreamEncoder"; to "fm/audioboo/jni/FLACStreamEncoder";

那并没有解决任何问题。

Java 代码调用一个函数,在该 native 函数执行之前,看起来艺术框架本身正在调用 FindClass(_JNIEnv*, char const*) 在第二个参数中使用错误的字符分隔符。如果您查看 pastebin 链接的第 46-48 行,它看起来不像是曾经调用过 native 函数。该框架只是抛出 bad package name Findclass 错误。请注意, native 函数的第一行是运行时未到达的日志语句。

Java 层...

  public FLACStreamEncoder(String outfile, int sample_rate, int channels,
      int bits_per_sample)
  {
    init(outfile, sample_rate, channels, bits_per_sample);
  }

...
  native private void init(String outfile, int sample_rate, int channels,
      int bits_per_sample);

...
  static {
    System.loadLibrary("audioboo-native");
  }

CPP 层 ... 该函数永远不会到达第一行日志 stmt。

extern "C" {

void
Java_fm_audioboo_jni_FLACStreamEncoder_init(JNIEnv * env, jobject obj,
    jstring outfile, jint sample_rate, jint channels, jint bits_per_sample)
{
    aj::log(ANDROID_LOG_DEBUG, LTAG, "Begin INIT extern call");
  assert(sizeof(jlong) >= sizeof(FLACStreamEncoder *));

  FLACStreamEncoder * encoder = new FLACStreamEncoder(
      aj::convert_jstring_path(env, outfile), sample_rate, channels,
      bits_per_sample);

  char const * const error = encoder->init();
  if (NULL != error) {
    delete encoder;

    aj::throwByName(env, IllegalArgumentException_classname, error);
    return;
  }

  set_encoder(env, obj, encoder);
}

一切正常(jni 构建/android buid/android-java 调用 cpp)直到使用 ndk 10-C 构建 android 5

android5/ART 的新功能似乎是“check_jni.cc”和某种给出错误的严格模式:

D/FLACRecorder(26743): Setting up encoder /data/data/com.borneo.speech/files/20141123081747.flac rate: 22050 channels: 1 format 16
F/art     (26743): art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: illegal class name 'fm.audioboo.jni.FLACStreamEncoder'
F/art     (26743): art/runtime/check_jni.cc:65]     (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')
F/art     (26743): art/runtime/check_jni.cc:65]     in call to FindClass
F/art     (26743): art/runtime/check_jni.cc:65]     from void fm.audioboo.jni.FLACStreamEncoder.init(java.lang.String, int, int, int)
F

full stacktrace:注意第 46 - 48 行

查看日志,就好像框架正在使用 CPP 中的第二个“thisClazz”arg 对“findClass”进行自己的调用:

Java_fm_audioboo_jni_FLACStreamEncoder_init(JNIEnv * env, jobject obj, ...  

它是一个错误的 arg 值,违反了艺术运行时检查。

但我没有运行“javah”来从 java 接口(interface)创建任何 header ,因为这一切都在我获得 git 项目之前完成。

我被难住了。 native 似乎到达了函数,从未到达函数的第一行(log statemt),在

上立即失败
 /system/lib/libart.so (art::CheckJNI::FindClass(_JNIEnv*, char const*)+66

ndk(R10C)链接cpp类如下:

make: Entering directory `/home/rob/tmp/audioboo-android/app/src/main/jni'
[armeabi-v7a] Compile thumb  : audioboo-ogg <= bitwise.c
[armeabi-v7a] Compile thumb  : audioboo-ogg <= framing.c
[armeabi-v7a] StaticLibrary  : libaudioboo-ogg.a
[armeabi-v7a] Compile thumb  : audioboo-flac <= bitmath.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= bitreader.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= cpu.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= crc.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= fixed.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= float.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= format.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= lpc.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= md5.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= memory.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= metadata_iterators.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= metadata_object.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= ogg_decoder_aspect.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= ogg_encoder_aspect.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= ogg_helper.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= ogg_mapping.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= stream_decoder.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= stream_encoder.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= stream_encoder_framing.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= window.c
[armeabi-v7a] Compile thumb  : audioboo-flac <= bitwriter.c
[armeabi-v7a] StaticLibrary  : libaudioboo-flac.a
[armeabi-v7a] Compile++ thumb: audioboo-native <= FLACStreamEncoder.cpp
[armeabi-v7a] Compile++ thumb: audioboo-native <= FLACStreamDecoder.cpp
[armeabi-v7a] Compile++ thumb: audioboo-native <= util.cpp
[armeabi-v7a] StaticLibrary  : libstdc++.a
[armeabi-v7a] SharedLibrary  : libaudioboo-native.so
[armeabi-v7a] Install        : libaudioboo-native.so => libs/armeabi-v7a/libaudioboo-native.so
make: Leaving directory `/home/rob/tmp/audioboo-android/app/src/main/jni'

Android 在 NP 之上加载库 audioboo-native 然后抛出

JNI DETECTED ERROR IN APPLICATION: illegal class name 'fm.audioboo.jni.FLACStreamEncoder''

关于从 Java 调用 native 函数,我不知道为什么?

最佳答案

我在升级到 Android 5 时遇到了同样的问题,并且刚刚解决了它。

错误存在于您的 native 代码中,而不存在于您的 Java 代码中。在您的 native 代码中的某处,您有一个函数,该函数通过 jni 作为 jobject 传递一个 FlacStreamEncoder 对象,您可以使用如下行检索它:

    jclass streamEncoder = env->FindClass("fm.audioboo.jni.FLACStreamEncoder");

但是 JNI 应该使用“/”作为分隔符而不是“.”,所以这一行应该是:

    jclass streamEncoder = env->FindClass("fm/audioboo/jni/FLACStreamEncoder");

相反。以前的 android 版本默默地忽略了这个问题,但现在它却在你面前炸开了锅。

来自 https://android.googlesource.com/platform/art/+/kitkat-dev/runtime/check_jni.cc

    // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
    // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
    // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
    // circumstances, but this is incorrect
    void CheckClassName(const char* class_name) {
        if (!IsValidJniClassName(class_name)) {
            JniAbortF(function_name_,
                      "illegal class name '%s'\n"
                      " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
                      class_name);
            }
        }
    }

关于android-ndk - android art runtime check_jni.cc 包名错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27092044/

相关文章:

android-ndk - 将android ndk构建文件转换为gradle

c - 迁移到实验性 gradle Android Studio 2.0+ 时包含的问题

java - Delphi/Android 在哪里搜索本地语言库?

android - 在 Android 中使用 openGL 绘制动态图形

android - 未定义对myfunction的引用

android - 启用 renderscript 使应用程序忽略 jniLibs

java - jstring 到 char* 在 c 用法中未转换为可打印格式

bluetooth-lowenergy - Android : iBeacon - read its advertisement (e. g txPower)

Android - 在 CoordinatorLayout 中使用时页脚滚动到屏幕外

android - Genymotion 不从 API 21 开始