Android:加载接口时DexClassLoader类加载失败

时间:2016-06-29 13:33:18

标签: java android classloader dalvik dexclassloader

简介:我正在尝试从运行时从classes.jar中的classes.dex加载代码。我做了很多研究,花了很多时间在这上面,所以我真的需要帮助。

问题:当我的jar包含一个简单的类时,它会成功加载。但是,在我的jar包含相同类的情况完全相同的情况下,只有现在该类实现了接口,加载此类失败并显示错误:

  

“在路径上找不到类”com.x.y.z.w.Patch“:DexPathList [[zip文件]   “/data/user/0/x.y.z/app_dex/classes_dexed.jar"],nativeLibraryDirectories=[/vendor/lib64,   /系统/ lib64下]]“

我也得到:

  

I / dalvikvm:解析Lcom / x / y / TestClassImpl失败;界面4   'LCOM / X / Y / TestClassInterface;'

环境:   - 用于尝试加载类的函数:

(DexClassLoader实例).loadClass& (DexFile实例).loadClass。

具体做法是:

方法1:

DexFile dx = DexFile.loadDex(jarInternalPath, File.createTempFile("opt", "dex", 
    context.getCacheDir()).getPath(), 0);
Class<?> targetClass = dx.loadClass(className, 
    ClassLoader.getSystemClassLoader()); // Error

方法2:

DexClassLoader dexClassLoader = new DexClassLoader(jarInternalPath,
    dexOutPath.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
Class<?> targetClass = dexClassLoader.loadClass(className); // Error
  • IDE:Android Studio 2.1.2
  • 测试设备:仿真器Nexus 4(带有API 16,19和23),还带有Android 6.0.1的物理Nexus 5设备
  • 最令人惊讶的事情:当我打印dex文件的类时,我看到了正确的类路径。我使用DexFile加载dex内容并打印其类路径。 此方法可识别正确的内容!这让我觉得这与Android权限或Linux权限有关。我不知道..

这是我的打印方法:

try {
    DexFile dx = DexFile.loadDex(jarInternalPath, File.createTempFile("opt", "dex",
        context.getCacheDir()).getPath(), 0);

    // Print all classes in the DexFile
    for (Enumeration<String> classNames = dx.entries(); classNames.hasMoreElements();) {
        String className = classNames.nextElement();
        Log.d(TAG, "Analyzing dex content, fonud class: " + className);
    }
} catch (IOException e) {
    Log.d(TAG, "Error opening " + jarInternalPath, e);
}
  • P.S。似乎不相关但可能不是:我的主机应用程序,通用界面和新内容的实现都位于同一项目的3个不同模块中。该应用程序的包名称为x.y.z,该接口的pkgName为x.y.z.interface,实现的pkgName为x.y.z.impl。

我尝试了同一个模块中的所有3个模块的第二个项目,1个模块无法以相同的方式工作。

请帮忙!

1 个答案:

答案 0 :(得分:0)

这还不足以加载你的课程。您必须更改系统类加载器,以便从动态和编程方式使用dex自己的类。如果不是你不能使用你的界面或类或其他什么。

如果你想动态加载类,首先从dexfile或dexclassloader加载类,然后使用它。

例如,

Class<?> myOwnClass = MyDexClassLoader.loadClass("com.example.my");