【问题标题】:Exclude JAR from DEX从 DEX 中排除 JAR
【发布时间】:2014-11-05 02:57:27
【问题描述】:

我想在运行时将一些类从 APK 加载到已经运行的服务中,但我收到以下错误:

11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ Class resolved by unexpected DEX: Lcom/somecompany/android/core/db/DatabaseManager;(0x2ce11280):0x392d6000 ref [Lcom/somecompany/android/core/CoreModule;] Lcom/somecompany/android/core/CoreModule;(0x2cdb1d20):0x38f40000
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ (Lcom/somecompany/android/core/db/DatabaseManager; had used a different Lcom/somecompany/android/core/CoreModule; during pre-verification)
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ Unable to resolve superclass of Lcom/somecompany/android/core/db/DatabaseManager; (720)
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ Link of class 'Lcom/somecompany/android/core/db/DatabaseManager;' failed
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ threadid=11: thread exiting with uncaught exception (group=0x2c7dbfc0)
11-03 16:51:13.570  20227-20240/com.somecompany.android.core E/com.somecompany.android.core.CoreApplication﹕ Thread com.somecompany.android.core.CoreService-80000000 has crashed
11-03 16:51:13.570  20227-20240/com.somecompany.android.core E/com.somecompany.android.core.CoreApplication﹕ java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
            at dalvik.system.DexFile.defineClass(Native Method)
            at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:211)
            at dalvik.system.DexPathList.findClass(DexPathList.java:315)
            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:58)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
            at com.somecompany.android.core.CoreModuleLoader.loadRegisterModules(CoreModuleLoader.java:56)
            at com.somecompany.android.core.CoreModuleLoader.load(CoreModuldeLoader.java:110)
            at com.somecompany.android.core.CoreService$1.run(CoreService.java:148)
            at java.lang.Thread.run(Thread.java:856)

我认为问题在于Android自动构建生成的APK将所有Service类打包到APK中,这在加载时会导致问题,因为这些相同的类已经存在于Service中。该服务在编译时链接为 JAR。

如何修改构建过程,使服务 JAR 不包含在生成的 APK 中?提前致谢。

编辑:APK 内的classes.dex 确实有服务类。

编辑:这是用于 DEX JAR 的 build.xml 节点。不幸的是,我不知道如何配置这部分的 ANT,任何帮助表示赞赏。

<!-- Configurable macro, which allows to pass as parameters output directory,
     output dex filename and external libraries to dex (optional) -->
<macrodef name="dex-helper">
    <element name="external-libs" optional="yes" />
    <attribute name="nolocals" default="false" />
    <sequential>
        <!-- sets the primary input for dex. If a pre-dex task sets it to
             something else this has no effect -->
        <property name="out.dex.input.absolute.dir" value="${out.classes.absolute.dir}" />

        <!-- set the secondary dx input: the project (and library) jar files
             If a pre-dex task sets it to something else this has no effect -->
        <if>
            <condition>
                <isreference refid="out.dex.jar.input.ref" />
            </condition>
            <else>
                <path id="out.dex.jar.input.ref">
                    <path refid="project.all.jars.path" />
                </path>
            </else>
        </if>

        <dex executable="${dx}"
                output="${intermediate.dex.file}"
                dexedlibs="${out.dexed.absolute.dir}"
                nolocals="@{nolocals}"
                forceJumbo="${dex.force.jumbo}"
                disableDexMerger="${dex.disable.merger}"
                verbose="${verbose}">
            <path path="${out.dex.input.absolute.dir}"/>
            <path refid="out.dex.jar.input.ref" />
            <external-libs />
        </dex>
    </sequential>
</macrodef>

【问题讨论】:

  • 这似乎总是偶然发生在人们身上......可能有用的一件事是将jar链接到你的java构建路径但不在android设置下。另一个是删除它的proguard规则。
  • @ChrisStratton 该服务实际上在构建路径中链接为 JAR。我会检查proguard,谢谢。
  • @ChrisStratton 我认为 ProGuard is not the way to go.

标签: android apk dex


【解决方案1】:

正如here 解释的那样,我创建了一个compile-libs/ 文件夹并将Service JAR 移到那里(从libs/ 中删除它)。然后我创建了一个 custom_build.xml 并包含这个 JAR 仅用于编译(不用于 dexing)。

<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules">

    <path id="java.compiler.classpath.path">
        <fileset dir="compile-libs" includes="*.jar" />
    </path>
    <property name="java.compiler.classpath" refid="java.compiler.classpath.path" />

</project>

这似乎已经解决了问题,因为生成的 DEX 没有来自 Service JAR 的类。

编辑:进一步测试确认它按预期工作。

【讨论】:

    猜你喜欢
    • 2014-07-13
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 2011-03-16
    • 2013-07-13
    相关资源
    最近更新 更多