安卓dex类加载器 - 找不到类

3
我想使用dex类加载器将代码动态加载到我的Android应用程序中。我已经按照这个教程进行了操作:http://www.marioalmeida.eu/2015/01/27/how-to-easy-way-load-apk-classes-using-dexclassloader/。然而,我得到了以下错误堆栈跟踪:
01-08 12:25:38.007 15147-15147/com.ph.dexloader W/System.err: java.lang.ClassNotFoundException: Didn't find class "com.ph.injection.Injection" on path: DexPathList[[zip file "/storage/emulated/0/testjars/injector.apk"],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at com.ph.dexloader.MainActivity.test3(MainActivity.java:153)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at com.ph.dexloader.MainActivity$1.onClick(MainActivity.java:34)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at android.view.View.performClick(View.java:5198)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at android.view.View$PerformClick.run(View.java:21147)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at android.os.Looper.loop(Looper.java:148)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:   Suppressed: java.io.IOException: No original dex files found for dex location /storage/emulated/0/testjars/injector.apk
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexFile.openDexFileNative(Native Method)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexFile.openDexFile(DexFile.java:295)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexFile.<init>(DexFile.java:111)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexFile.loadDex(DexFile.java:151)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexPathList.loadDexFile(DexPathList.java:282)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexPathList.makePathElements(DexPathList.java:248)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexPathList.<init>(DexPathList.java:120)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:48)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.DexClassLoader.<init>(DexClassLoader.java:57)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at com.ph.dexloader.MainActivity.test3(MainActivity.java:146)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:       ... 10 more
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:   Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.ph.injection.Injection" on path: DexPathList[[zip file "/data/app/com.ph.dexloader-2/base.apk"],nativeLibraryDirectories=[/data/app/com.ph.dexloader-2/lib/x86, /vendor/lib, /system/lib]]
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:       ... 12 more
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:       Suppressed: java.lang.ClassNotFoundException: Didn't find class "com.ph.injection.Injection" on path: DexPathList[[dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-support-annotations-24.1.0_ae5436f3e75e322599cc28c891c7bbfb3749511e-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-internal_impl-24.1.0_3cdb966acce2459aa95bcd6df4240d298e8a6aa0-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-com.android.support-support-vector-drawable-24.1.0_68483e445bfd7fe2615d6637e23aa54f7eca71ad-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-com.android.support-support-v4-24.1.0_0b01882602c790d27bb53e6d99c19f41bfa0f42f-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-com.android.support-appcompat-v7-24.1.0_ffbd2666f53be3072a55297d806cbb863283a31e-classes.dex", dex file "/data/data/com.ph.dexloader/files/instant-run/dex/slice-com.android.support-animated-vector-drawable-24.1.0_fa7ca9f78df22fc1c453fed6517df1a2457fbf73-classes.dex"],nativeLibraryDirectories=[/data/app/com.ph.dexloader-2/lib/x86, /vendor/lib, /system/lib]]
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader.findClass(IncrementalClassLoader.java:90)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at com.android.tools.fd.runtime.IncrementalClassLoader.findClass(IncrementalClassLoader.java:62)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:           ... 13 more
01-08 12:25:38.008 15147-15147/com.ph.dexloader W/System.err:           Suppressed: java.lang.ClassNotFoundException: com.ph.injection.Injection
01-08 12:25:38.009 15147-15147/com.ph.dexloader W/System.err:     at java.lang.Class.classForName(Native Method)
01-08 12:25:38.009 15147-15147/com.ph.dexloader W/System.err:     at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
01-08 12:25:38.009 15147-15147/com.ph.dexloader W/System.err:     at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
01-08 12:25:38.009 15147-15147/com.ph.dexloader W/System.err:     at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
01-08 12:25:38.009 15147-15147/com.ph.dexloader W/System.err:               ... 14 more
01-08 12:25:38.009 15147-15147/com.ph.dexloader W/System.err:           Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

我创建了一个没有Activity的Android项目,并且想要加载以下类:

我创建了一个没有Activity的Android项目,并且想要加载以下类:

package com.ph.injection;

import android.util.Log;

public class Injection {

    public void inject() {
        /* this code is getting injected */
        Log.d("INJECTED", "This is injected code!");
    }
}

我使用gradle assemble生成APK文件,并将其放置在模拟器的/storage/emulated/0/testjars/injector.apk位置。

这是我用来加载DEX文件的代码:

    String dexFile = "/testjars/injector.apk";

    // Get the path to the SD card
    File f = new File(Environment.getExternalStorageDirectory().toString() + dexFile);
    final File optimizedDexOutputPath = getDir("outdex", 0);
    DexClassLoader classLoader = new DexClassLoader(f.getAbsolutePath(), optimizedDexOutputPath.getAbsolutePath(),null, getClassLoader());

    // The classpath is created for the new class
    String completeClassName = "com.ph.injection.Injection";
    String methodToInvoke = "inject";

    try {
        Class<?> myClass = classLoader.loadClass(completeClassName);
        Object obj = (Object) myClass.newInstance();
        Method m = myClass.getMethod(methodToInvoke);
        m.invoke(obj);
    }
    catch (Exception e) {
        e.printStackTrace();
    }

我不知道为什么DEX文件没有正确加载/类找不到。有人可以帮我吗?如果有影响的话,我使用的是Genymotion Android 6.0.0模拟器。

谢谢!


尝试禁用即时运行并查看是否有所帮助。 - Alex Lipov
很遗憾没有帮到你。不过还是谢谢你。 - Phoebus
你解决了这个问题吗? - Itay Bianco
1个回答

1
假设您遇到的问题与DexClassLoader无关,例如没有读写外部存储的权限,那么问题很可能是您没有将应用程序配置为支持multidex。在gradle中,您可以这样配置您的应用程序:
defaultConfig {
  …
  multiDexEnabled true
}

如果你的目标是api 26以下的应用程序,那么你还需要在mulitdex支持库上添加一个依赖项。这对于api 26及以上版本来说是不必要的,因为它已经嵌入到android中了。
如果你考虑一下,如果你试图加载外部代码,那么该代码存在于另一个dex文件中,因此你需要使你的应用程序启用multidex才能让它工作。大多数人只有在单个dex应用程序达到65K方法限制时才配置其应用程序为multidex启用。在运行时访问外部代码只是使你的应用程序启用multidex的另一个原因。注意:你引入的外部代码不必构建为multidex启用。
如果你的应用程序已经启用了multidex,则你无法找到类的消息(假设你正确指定了包含所需类的jar和类名)的另一个原因可能是你想要加载的类需要找不到的类。这可能有点棘手。你得到的错误消息是找不到你的类,而问题实际上是找不到一个依赖的类。
根据我的经验,像“关闭实例运行”和“禁用dex优化”这样的解决方案通常是偏离正确方向的,并且通常只与某些特定的旧版本有关,可能是测试版,并且已经得到了纠正。它们被称为阿司匹林解决方案,因为在某些情况下它们确实起作用,但潜在问题仍然是个谜。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接