java - JNI 检测到 ClassNotFoundException - 但类在 .apk/.dex 中可见?

标签 java android android-ndk

我遇到了一个我真的无法解决的问题。

首先,我编译了openFrameworks androidVideoExample对于 Ubuntu 14.04 上的 Android(我在命令行上使用了 gradlew assembleDebug);然后,使用 adb install ./build/outputs/apk/androidVideoExample-debug.apk 在 Android 设备上部署生成的 .apk .我已经部署在 Android 4.2.2 设备和 Android 6.0.1 设备上 - 它可以在两者上运行而不会崩溃。

然后,我尝试使用该示例中使用的视频组件 openFrameworks ofVideoPlayer ,在我的测试应用程序 ( myApp ) 的代码中,该应用程序以前在这些设备中的任何一个上构建并运行良好。当我构建它时 - 再次使用 gradlew assembleDebug - 构建良好,使用 adb install ./build/outputs/apk/myApp-debug.apk 也可以正常安装在两个设备上。但是,当我运行它时,它会在两台设备上启动时崩溃。

所以,我检查了 adb logcat - 4.2.2 设备没有给我有用的踪迹;然而,6.0.1 最终有这样的东西:

--------- beginning of crash
01-29 23:56:22.551  8938  8973 F libc    : Fatal signal 6 (SIGABRT), code -6 in tid 8973 (Thread-21892)
01-29 23:56:22.653   383   383 D clmlib  : Got activities:0x0000000E
01-29 23:56:22.654   383   383 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
01-29 23:56:22.654   383   383 F DEBUG   : UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
01-29 23:56:22.655   383   383 F DEBUG   : Build fingerprint: 'XXXXXXXXXXXXXXX:user/release-keys'
01-29 23:56:22.655   383   383 F DEBUG   : Revision: '0'
01-29 23:56:22.655   383   383 F DEBUG   : ABI: 'arm'
01-29 23:56:22.655   383   383 F DEBUG   : pid: 8938, tid: 8973, name: Thread-21892  >>> cc.openframeworks.myApp <<<
01-29 23:56:22.655   383   383 F DEBUG   : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
01-29 23:56:22.694   383   383 F DEBUG   : Abort message: 'art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.ClassNotFoundException: Didn't find class "cc.openframeworks.OFAndroidVideoPlayer" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]'
01-29 23:56:22.694   383   383 F DEBUG   :     r0 00000000  r1 0000230d  r2 00000006  r3 967e6978
01-29 23:56:22.694   383   383 F DEBUG   :     r4 967e6980  r5 967e6930  r6 0000000b  r7 0000010c
...

首先,请注意这些有关这些视频对象关系的 grep fragment :
openFrameworks/libs/openFrameworks/video/ofVideoPlayer.h:   #include "ofxAndroidVideoPlayer.h"

openFrameworks/addons/ofxAndroid/src/ofxAndroidVideoPlayer.cpp: jclass localClass = env->FindClass("cc/openframeworks/OFAndroidVideoPlayer");

openFrameworks/addons/ofxAndroid/ofAndroidLib/src/cc/openframeworks/OFAndroidVideoPlayer.java:public class OFAndroidVideoPlayer extends OFAndroidObject implements OnFrameAvailableListener {

好的,所以我认为消息'没有找到类“cc.openframeworks.OFAndroidVideoPlayer”'意味着我以某种方式从我的.apk中丢失了这些类;但是,我尝试了这个:
$ zipgrep OFAndroidVideoPlayer /path/to/build/outputs/apk/myApp-debug.apk
classes.dex:Binary file (standard input) matches
lib/armeabi-v7a/libOFAndroidApp.so:Binary file (standard input) matches

嗯,看起来他们在那里?试着看近一点,也使用 dexdump :
$ cd /tmp
$ mkdir unpack
$ cd unpack
$ unzip /path/to/build/outputs/apk/myApp-debug.apk
$ /path/to/sdk/build-tools/19.1.0/dexdump ./classes.dex | grep OFAndroidVideoPlayer
  Class descriptor  : 'Lcc/openframeworks/OFAndroidVideoPlayer$1;'
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$1;)
      type          : 'Lcc/openframeworks/OFAndroidVideoPlayer;'
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$1;)
      type          : '(Lcc/openframeworks/OFAndroidVideoPlayer;)V'
        0x0000 - 0x0006 reg=0 this Lcc/openframeworks/OFAndroidVideoPlayer$1;
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$1;)
        0x0000 - 0x0025 reg=2 this Lcc/openframeworks/OFAndroidVideoPlayer$1;
  source_file_idx   : 358 (OFAndroidVideoPlayer.java)
  Class descriptor  : 'Lcc/openframeworks/OFAndroidVideoPlayer$2;'
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$2;)
      type          : 'Lcc/openframeworks/OFAndroidVideoPlayer;'
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$2;)
      type          : '(Lcc/openframeworks/OFAndroidVideoPlayer;)V'
        0x0000 - 0x0006 reg=0 this Lcc/openframeworks/OFAndroidVideoPlayer$2;
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$2;)
        0x0000 - 0x0001 reg=0 this Lcc/openframeworks/OFAndroidVideoPlayer$2;
  source_file_idx   : 358 (OFAndroidVideoPlayer.java)
  Class descriptor  : 'Lcc/openframeworks/OFAndroidVideoPlayer$3;'
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$3;)
      type          : 'Lcc/openframeworks/OFAndroidVideoPlayer;'
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$3;)
      type          : '(Lcc/openframeworks/OFAndroidVideoPlayer;)V'
        0x0000 - 0x0006 reg=0 this Lcc/openframeworks/OFAndroidVideoPlayer$3;
    #0              : (in Lcc/openframeworks/OFAndroidVideoPlayer$3;)
        0x0000 - 0x0007 reg=2 this Lcc/openframeworks/OFAndroidVideoPlayer$3;
  source_file_idx   : 358 (OFAndroidVideoPlayer.java)
...
    #28              : (in Lcc/openframeworks/OFAndroidVideoPlayer;)
        0x0000 - 0x001d reg=2 this Lcc/openframeworks/OFAndroidVideoPlayer;
  source_file_idx   : 358 (OFAndroidVideoPlayer.java)

好吧——至少这是说cc/openframeworks/OFAndroidVideoPlayerclasses.dex ,在我的 .apk - 所以这应该意味着类(class)在那里?事实上,dexdump ./classes.dex ... | grep OFAndroidVideoPlayer myApp-debug.apk 的输出相同对于 androidVideoExample-debug.apk !

我也试过dex-method-counts , 对于 myApp-debug.apk “总体方法计数:710”,因此它远低于需要 multidex 的 65536 限制.

否则,这些类将由 openFrameworks 在这里编译:
$ find /path/to/openFrameworks/ -name '*AndroidVideoPla*'
...
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer$3.class
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer.class
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer$2.class
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer$1.class
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer$3.class
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer.class
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer$2.class
/path/to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer$1.class

因此,4 个用于调试的 Java 类和 4 个用于发布的 Java 类——我猜这些最终会出现在 classes.dex 中。 .

最后,我开始以二进制方式在这些项目的源文件夹中grep,希望能找到不同之处:
grep -rao .......OFAndroidVideoPlayer...... . | tr -cd '\11\12\40-\176' > /tmp/a2

...我将这些输出与 meld 进行了比较.我唯一能找到的是 myApp源文件夹将这些作为重复条目:
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer.class
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer$1.cla
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer$3.cla
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/release/cc/openframeworks/OFAndroidVideoPlayer$2.cla
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer.class
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer$2.cla
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer$3.cla
 ./.gradle/2.4/taskArtifacts/fileSnapshots.bin: /to/openFrameworks/addons/ofxAndroid/ofAndroidLib/build/intermediates/classes/debug/cc/openframeworks/OFAndroidVideoPlayer$1.cla

现在这些是 gradlew 中的重复项的fileSnapshots.bin - 不在 .apk 中本身 - 所以我没有得到重复的类错误(他们得到,比如说, here )。而且,除了 OFAndroidVideoPlayer 的现有条目之外,这些都是重复的。在 fileSnapshots.bin在这两个项目中。然后我只是简单地删除了.gradle/2.4/taskArtifacts/的内容目录:
rm -rfv .gradle/2.4/taskArtifacts/*

...然后我做了gradlew assembleDebug重建myApp再次 - 这一次,fileSnapshots.bin 中没有重复项。 (所以 myAppfileSnapshots.binOFAndroidVideoPlayer 的引用数量与 androidVideoExample 相同)。但是,该应用程序在启动时仍然崩溃,并出现完全相同的错误。

所以,据我所知,OFAndroidVideoPlayer类(class)在.dex.apk对于 myApp - 但是 JNI 在运行时仍然看不到它们,在应用程序启动期间?这可能是什么原因 - 我该如何进一步调试?

例如,我还有什么其他方法可以比较工作 androidVideoExample 之间的差异? ,以及崩溃的 myApp ,关于“失踪”cc.openframeworks.OFAndroidVideoPlayer Java 类?

最佳答案

请注意,搜索路径中没有 dex 文件:

...on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib]]'

通常,当有人附加一些以 native 启动的线程然后尝试加载 Java 类时,就会发生这种情况。此类线程的默认类加载器不知道您的 dex'es。您可以尝试从最初在 java 中创建的任何线程执行该查找。从 JNI_OnLoad() 执行此操作将是理想的。

关于java - JNI 检测到 ClassNotFoundException - 但类在 .apk/.dex 中可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48512872/

相关文章:

java - Android JNI 检测到应用程序错误 : JNI GetMethodID called with pending exception

java - CompletableFuture 跨微服务(JVM)

java - 我不知道如何设置按钮之间的距离

java - javadoc 的默认值

android - 具有两列的 ListView,具有单独的 onItemClick - Android

android - JSONObject toString 有时会抛出 ConcurrentModificationError

java - 使用 root Android 应用程序运行二进制文件

java - 从 JNI 返回三个 Mat 框架

java - 事务和分离对象 JPA

android - 通过 adb 自动无线连接 Android 设备和 IntelliJ