Android ClassLoader:如果类实现了接口,则loadClass失败

时间:2015-04-13 10:28:20

标签: java android reflection interface classloader

我正在使用以下代码从外部包动态加载类:

Object plugin = null;
    String packageName = "unipd.elia.deltapluginaccelerometersensor";
    String className = "unipd.elia.deltapluginaccelerometersensor.AccelerometerPlugin";
    try {
        PackageManager packageManager = getPackageManager();
        ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
        DexFile df = new DexFile(appInfo.sourceDir);
        ClassLoader cl = getClassLoader();
        Class classToInvestigate = df.loadClass(className, cl);
        plugin = classToInvestigate.newInstance();


    } catch (Exception e) {
        System.out.println("EXCEPTION");
    }

问题如下:如果我尝试加载的类是一个“简单”类,一切都很顺利,但如果它实现了一个接口,加载就会失败。这是一个无法加载的类的示例:

    package unipd.elia.deltapluginaccelerometersensor;

public class AccelerometerPlugin implements IDeltaPlugin {

    @Override
    public String getPluginName() {
        return "Accelerometer Sensor Plugin";
    }

    @Override
    public String getPluginID() {
        return "delta.plugin.accelerometersensor";
    }

    @Override
    public String getPluginAuthor() {
        return "Me";
    }
}

它实现的界面:

public interface IDeltaPlugin {

    String getPluginName();
    String getPluginID();
    String getPluginAuthor();
}

如果类实现接口,基本上对loadClass()的调用返回null。删除“implements”语句,它加载正常。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

好吧,事实证明问题在于有问题的界面是在正在进行加载的应用程序和定义要加载的类的apk共享的Android库项目中。

然后ClassLoader会混淆,因为它在类路径中找到了相同接口的两个副本。

解决方案:将共享库转换为JAR库,并在插件中将其导入"提供" (而不是"编译")模式。这样只存在一个接口副本(apk中正在进行类加载的那个)