这样写Android兼容代码安全吗?
在Android上编写这样的兼容代码安全吗这样写Android兼容代码安全吗?,android,dalvik,Android,Dalvik,在Android上编写这样的兼容代码安全吗 if (Build.os.SDK_INT >= 11) { newClass instance = new newClass(); .... } else { oldClass instance = new oldClass(); .... } 我的一位同事与我争辩说,运行上述代码时可能会抛出ClassNotFoundException,因为ClassLoader试图在低于android 11的android操作
if (Build.os.SDK_INT >= 11) {
newClass instance = new newClass();
....
}
else {
oldClass instance = new oldClass();
....
}
我的一位同事与我争辩说,运行上述代码时可能会抛出ClassNotFoundException,因为ClassLoader试图在低于android 11的android操作系统设备上加载newClass。但我试过好几次,都没看到这种情况发生。
在谷歌搜索了几个小时后,我没有找到任何关于android默认类加载器如何以及何时加载特定类的信息 您应该检查兼容性,如下所示。。。它比上述内容更准确:
private static int currentApi = 0;
public static int getApiLevel() {
if (currentApi > 0) {
return currentApi;
}
if (android.os.Build.VERSION.SDK.equalsIgnoreCase("3")) {
currentApi = 3;
} else {
try {
Field f = android.os.Build.VERSION.class.getDeclaredField("SDK_INT");
currentApi = (Integer) f.get(null);
} catch (Exception e) {
return 0;
}
}
return currentApi;
}
简短的回答-不要这样做 大多数虚拟机仅在绝对需要时加载类。但是,允许类加载器预先缓存类的二进制表示形式[1] 类装入器可以缓存类型的二进制表示形式, 预期最终使用的早期荷载类型,或荷载类型 在相关的小组里一起 [1] - [2] -
编辑-你是否检查过你需要的类是否作为android支持包的一部分提供?[2] 您始终可以使用
反射检查类是否存在:
try {
Class.forName("yourclass")
} catch (ClassNotFoundExecption) {
oldClass instance = new oldClass();
}
是的,在最新版本的Android上这样做是安全的。我想说froyo及以上,但可能比这更早。我记不清了
发生的情况是dalvik在安装时对dex文件执行验证传递。对于无法解析的任何类/方法/字段,它将用抛出VerifyError的指令替换这些访问
在您的示例中,如果加载了该代码,例如api 10,newClass instance=new newClass()
将在概念上替换为throw new VerifYError()
。因此,只要该分支永远不会在运行时执行,一切都很好。当然,在Android上使用反射是可行的。然而,反射同时带来了性能问题,这就是为什么我试图避免使用它。在我看来,使用支持库是最后的选择,因为它会增加apk的大小。换句话说,如果类加载器在早期加载期间遇到丢失或格式不正确的类文件,它必须等待报告该错误,直到该类首次被程序激活。如果程序从未主动使用该类,则类装入器将永远不会报告错误。似乎只有当类被程序积极使用时才会引发异常。但这是jvm规范,我不确定android上的dalvik vm是如何处理这个问题的。我仍然会使用支持包,而不是编写有条件加载类的代码。V13的支持类只引入了大约400kb的开销。谢谢,这涵盖了android版本4以下的设备。当最小SDK版本大于4时,直接使用SDK_INT是安全的。是的,您可以直接使用SDK_INT