我正在尝试根据我的需要调整http://android-developers.blogspot.de/2011/07/custom-class-loading-in-dalvik.html中的示例。为此,我设置了 3 个项目:
classloadingtest:标准android应用项目,包含上面链接中MainActivity的源码,稍作调整(将DexClassLoader业务移到名为“AndroidClassLoader”的类中),参考下面的“iface”项目
iface:一个android库项目,只包含一个接口,只有一个函数(“getMessage()”)返回一个字符串
loadable:一个标准的 android 应用程序项目,还引用了“iface”库,其中仅包含一个实现该非常简单接口的类,并带有一个 custom_rules.txt 文件来调整构建过程:
<?xml version="1.0" encoding="UTF-8"?>
<project name="BuildLoadableDex" default="debug">
<target name="-dex" depends="-compile, -post-compile, -obfuscate">
<echo level="info">Custom -dex target</echo>
<property name="out.dex.input.absolute.dir" value="${out.classes.absolute.dir}" />
<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}"/>
</dex>
</target>
<target name="-package" depends="-dex, -package-resources">
<echo level="info">Custom -package target</echo>
<jar destfile="${out.absolute.dir}/${ant.project.name}.jar"
basedir="${out.absolute.dir}"
includes="${dex.file.name}" />
</target>
</project>
所以这实际上只是修改了 -dex 目标以从 classes.dex 文件中省略库类(通过 dexdump 验证未显示接口)并更改 -package 目标以输出 jar 文件而不是 apk。
然后我将 loadable.jar 文件复制到 classloadingtest/assets 并构建该 apk 文件。
一切都编译得很好,但是在运行和触发类加载时,我得到以下堆栈跟踪:
W/dalvikvm(14393): Class resolved by unexpected DEX: Lloadable/Test;(0x4294b620):0x5a6a7000 ref [Lclassloading/iface/LoadableClass;] Lclassloading/iface/LoadableClass;(0x42912fb8):0x5a4bf000
W/dalvikvm(14393): (Lloadable/Test; had used a different Lclassloading/iface/LoadableClass; during pre-verification)
I/dalvikvm(14393): Failed resolving Lloadable/Test; interface 6 'Lclassloading/iface/LoadableClass;'
W/dalvikvm(14393): Link of class 'Lloadable/Test;' failed
D/AndroidRuntime(14393): Shutting down VM
W/dalvikvm(14393): threadid=1: thread exiting with uncaught exception (group=0x41c622a0)
E/AndroidRuntime(14393): FATAL EXCEPTION: main
E/AndroidRuntime(14393): java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
E/AndroidRuntime(14393): at dalvik.system.DexFile.defineClass(Native Method)
E/AndroidRuntime(14393): at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:211)
E/AndroidRuntime(14393): at dalvik.system.DexPathList.findClass(DexPathList.java:315)
E/AndroidRuntime(14393): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:58)
E/AndroidRuntime(14393): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
E/AndroidRuntime(14393): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
E/AndroidRuntime(14393): at classloading.loading.AndroidClassLoader.findClass(AndroidClassLoader.java:56)
E/AndroidRuntime(14393): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
E/AndroidRuntime(14393): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
E/AndroidRuntime(14393): at classloading.loading.AndroidClassLoader.loadClass(AndroidClassLoader.java:37)
E/AndroidRuntime(14393): at classloading.ClassLoadingTest$1.onClick(ClassLoadingTest.java:60)
E/AndroidRuntime(14393): at android.view.View.performClick(View.java:4211)
E/AndroidRuntime(14393): at android.view.View$PerformClick.run(View.java:17267)
E/AndroidRuntime(14393): at android.os.Handler.handleCallback(Handler.java:615)
E/AndroidRuntime(14393): at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime(14393): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(14393): at android.app.ActivityThread.main(ActivityThread.java:4898)
E/AndroidRuntime(14393): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(14393): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(14393): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
E/AndroidRuntime(14393): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
E/AndroidRuntime(14393): at dalvik.system.NativeStart.main(Native Method)
我确实知道这意味着 LoadableClass 接口“似乎”以某种方式存在两次但存在差异,但我无法理解这是如何发生的,看到 APK(classloadingtest)和 loadable.jar 都使用完全相同的库项目用于编译,因此我不知道如何修复此错误。
请随时请求使用更多代码进行编辑,我只是不知道这里有什么用处,也不想粘贴所有内容。