简体   繁体   English

从DEX中排除JAR

[英]Exclude JAR from DEX

I want to load some classes from an APK into an already running Service at runtime, but I get the following error: 我想在运行时将一些类从APK加载到已经运行的Service中,但是出现以下错误:

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)

I think the problem is that the APK generated by Android automatic build packs all the Service classes into the APK, which at time of loading causes problems because these same classes already exist into the Service. 我认为问题是Android自动生成的APK将所有Service类打包到APK中,在加载时会引起问题,因为这些相同的类已经存在于Service中。 The Service is linked as a JAR at compile time. 该服务在编译时作为JAR链接。

How can I modify the build process so the Service JAR is NOT included in resulting APK? 如何修改构建过程,以使Service JAR不包含在结果APK中? Thanks in advance. 提前致谢。

EDIT: classes.dex inside the APK does have the Service classes. 编辑:APK内的classes.dex确实具有Service类。

EDIT: this is the build.xml node used to DEX the JARs. 编辑:这是用于DEX JAR的build.xml节点。 Unfortunately I have no idea about ANT on how to configure this part, any help appreciated. 不幸的是,我对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>

As explained here , I created a compile-libs/ folder and moved the Service JAR there (removing it from libs/ ). 正如解释在这里 ,我创建了一个compile-libs/文件夹,移动服务JAR那里(从取出libs/ )。 Then I created a custom_build.xml and included this JAR only for compilation (not for dexing). 然后,我创建了一个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>

This looks like to have solved the problem as the generated DEX does not have the classes from the Service JAR. 这似乎解决了问题,因为生成的DEX没有Service JAR中的类。

EDIT: further testing confirms it is working as expected. 编辑:进一步测试确认它正在按预期方式工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM