android - 在 Android 中嵌入 OSGi Felix 导致 UnsupportedOperationException : can't load this type of class file

标签 android gradle osgi activator

我有一个使用 AndroidStudio 和 Gradle 开发的 android 项目,它嵌入并启动了一个基于 felix 的小型 OSGi 项目。为了调试,我使用 Nexus 5X 模拟器和 Android 8.0,API 26。我使用声明式服务,因此我的项目基于 felix.main、felix.scr 和 felix.configadmin。所有的 bundle 都是 dexified 的。安装 bundle 工作正常,但如果我通过 bundle.start() 启动 bundle ,我会收到以下关于 felix.scr 和 felix.configadmin 的错误消息(felix.main 和我自己的 bundle 工作正常 -> 状态处于 Activity 状态):

08-03 13:58:00.880 19745-19745/android.cit.tu_berlin.de.helloandroid W/zygote: Skipping duplicate class check due to unrecognized classloader
    08-03 13:58:00.881 19745-19745/android.cit.tu_berlin.de.helloandroid E/OSGIService: catch exception while starting bundle:
    08-03 13:58:00.881 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err: org.osgi.framework.BundleException: Activator start error in bundle org.apache.felix.configadmin [2].
    08-03 13:58:00.881 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.Felix.activateBundle(Felix.java:2276)
    08-03 13:58:00.881 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.Felix.startBundle(Felix.java:2144)
    08-03 13:58:00.881 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)
    08-03 13:58:00.881 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984)
    08-03 13:58:00.881 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.cit.tu_berlin.de.helloandroid.OSGIService.startBundle(OSGIService.java:386)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.cit.tu_berlin.de.helloandroid.OSGIService.runSensorVisualisationPlugin(OSGIService.java:248)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.cit.tu_berlin.de.helloandroid.OSGIService.onStartCommand(OSGIService.java:158)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3539)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.app.ActivityThread.-wrap20(Unknown Source:0)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1698)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:105)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.os.Looper.loop(Looper.java:164)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6540)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err: Caused by: java.lang.UnsupportedOperationException: can't load this type of class file
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at java.lang.ClassLoader.defineClass(ClassLoader.java:591)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.defineClass(BundleWiringImpl.java:2370)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2154)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1542)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.BundleWiringImpl.getClassByDelegation(BundleWiringImpl.java:1415)
    08-03 13:58:00.882 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:4468)
    08-03 13:58:00.883 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:     at org.apache.felix.framework.Felix.activateBundle(Felix.java:2221)
    08-03 13:58:00.883 19745-19745/android.cit.tu_berlin.de.helloandroid W/System.err:  ... 15 more

gradle 脚本具有以下语句来解析对 felix jars 的依赖关系:

provided fileTree(dir: 'src/main/assets/bundles/', include: ['*.jar'])
// for finding Felix.class
compile group: 'org.apache.felix', name: 'org.apache.felix.framework', version: '5.4.0'

我需要将以下属性设置为 felix 以解决对 osgi.ee 的缺失要求(基于 Christian Schneider 在 post 中的回答):

configMap.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, "osgi.ee; osgi.ee=\"JavaSE\";version:List=\"1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8\"");

我想知道该错误是否与 post 有关特别是“项目构建路径的引用库条目”部分(基于 Alec B. Plumb 在 post 中的回答)因为我不知道为什么“我的”错误报告的第一行说

W/zygote: Skipping duplicate class check due to unrecognized classloader

为什么要重复类?每个库都存在一次,除了 gradle 之外,没有进一步的项目设置或依赖关系链接。

我找到了一个类似的 post并按照 Apache Felix 教程步骤解决。很好,但我做了同样的事情,而且还发生了错误。

最近几天我尝试了很多,最近几天我读了很多书,但我猜我发现的内容与我的问题不符。请帮忙!提前致谢!

08.08.17 更新:

我试图根据 Balazs Zsoldos 的回答找到原始异常,结果如下: 在getClassByDelegation(String name)中的BundleWiringImpl.class中抛出异常:

public Class getClassByDelegation(String name) throws ClassNotFoundException {
        if(name != null && name.length() > 0 && name.charAt(0) == 91) {
            return Class.forName(name, false, this.getClassLoader());
        } else if(this.isFiltered(name)) {
            throw new ClassNotFoundException(name);
        } else {
            ClassLoader cl = this.getClassLoaderInternal();
            if(cl == null) {
                throw new ClassNotFoundException("Unable to load class \'" + name + "\' because the bundle wiring for " + this.m_revision.getSymbolicName() + " is no longer valid.");
            } else {
                return cl.loadClass(name);
            }
        }
    }

最后一行 (cl.loadClass(name)) 抛出异常。为了完整起见,这里的值:

cl = org.apache.felix.configadmin
name = org.apache.felix.cm.impl.ConfigurationManager

不幸的是我无法调试那个方法,所以我停在那里并设置 AndroidStudio 来捕获所有异常。下一站是DexFile.class抛出的异常导致的

cause = java.lang.ClassNotFoundException: java.lang.Object
detailedMessage = Failed resolution of: Ljava/lang/Object

这是什么鬼?为什么在 DexFile.class 中以及为什么无法解析对象类?我检查了 bundle jar 中的 dex 文件及其条目名称(可能是绝对路径问题,Balazs Zsoldos 提到)。好的!没有隐藏的添加。任何人都可以提供帮助或是否有人有类似的问题并且知道如何解决?

更新 10.08.17

我想知道的是为什么只有 felix 包会抛出异常。 Felix-Main bundle 和我自己的工作正常,它们处于 Activity 状态。为什么即使 felix-scr 包没有启动(状态已解决),我自己基于声明式服务的包也可能处于 Activity 状态。似乎 felix-scr 没有处于 Activity 状态以解决对 felix-scr 的依赖。 无论如何,为什么 dexified felix 库失败而我自己的工作?请帮忙,我很绝望!

2017 年 8 月 11 日更新

今天我尝试在物理安卓设备(索尼 XPERIA Z2 和安卓 4.4.4,API 19)上运行和调试我的项目,它工作正常。所有 bundle 都处于 Activity 状态。最近几天我使用了 Nexus 5X 的模拟器和 Android 8.0,API 26,所以我编辑了我的帖子以添加该信息。它似乎在很大程度上取决于设备和/或 android 版本和 API。疯了!

最佳答案

您最大的问题是由于 Apache Felix 的错误,您无法知道原始异常:https://issues.apache.org/jira/browse/FELIX-5643

如果基于Android的类加载过程中出现异常

  • 异常被吞噬
  • Felix 退回到正常的 JDK 类加载机制,抛出您看到的异常

我们可以通过两种方式暂时解决这个问题:

我们确实在 Android Studio 中的 BundleContextImpl.getDexFileClass(...) 函数的开头设置了一个断点,在它停止后,我们确实设置了 Android dev studio 以捕获所有异常。通过这样做,我们能够找到最初的原因。

第一个解决方案让我们感到疲倦,因为我们不得不打开和关闭异常停止功能。由于有许多 bundle 其中一个失败,因此在调试期间很难找到正确的 bundle 。因此,我们干脆把BundleWiringImpl类的内容复制到Android developer studio中,改成注销吞噬异常。通过这样做,我们能够在日志中看到原始异常。

顺便说一句:最烦人的问题如下。正如教程所说,我们对 jar 进行了 dexified。但是,aapt 命令太丑陋了,如果您使用绝对 URL 指定 classes.dex 文件,ZIP 的条目将具有相同的名称(如果您使用 Windows,则包括驱动器号)。例如:zip 中 classes.dex 的条目名称是 c:\classes.dex 并且没有 ZIP 编辑器显示其名称的 _c:_ 部分。因此,我们列出了ZIP/JAR在Java中的条目名称,以找出真正的条目名称。

关于android - 在 Android 中嵌入 OSGi Felix 导致 UnsupportedOperationException : can't load this type of class file,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45485759/

相关文章:

java - 如何在junit测试中模拟gradle构建脚本?

java - Gradle:从外部编译的类生成jar

android - 找不到GoogleMap类

dependency-injection - 我如何构建既可以作为 OSGI bundle 又可以作为 WAR 运行的应用程序

java - 基于 Maven 依赖项以编程方式构建和启动包含的应用程序

android - Google 地方信息自动完成无法加载搜索结果

android - Intent 值分别形成包含多个值的 ListView 行

java - 单击时如何在显示屏内滚动水平 ScrollView 的项目?

android - 如何通过微调器选择使编辑文本可编辑和不可编辑

java - OSGi - 获取接口(interface)的实现