正确使用Classloader(特别是在Android中)

时间:2010-05-09 21:23:34

标签: java android classloader

我阅读了一些关于类加载器的文档,但我仍然不确定它们的位置和原因。 Android API说:

  

从a加载类和资源   库。一个或多个类加载器   在运行时安装。这些是   每当运行时系统咨询   需要一个还没有的特定课程   在内存中可用。

因此,如果我理解这是正确的,那么可以有许多负责加载新类的classlaoders。但系统如何决定使用哪个?在哪种情况下,开发人员应该实例化一个新的类加载器?

在Intent的Android API中有一个方法

public void  setExtrasClassLoader  (ClassLoader  loader)

描述说:

  

设置将使用的ClassLoader   当解组任何Parcelable时   来自此Intent的额外内容的值。

那么我可以定义一个特殊的类加载器,以便我可以使用未在接收活动中定义的Intent传递对象吗?一个例子:

如果位于项目A(在Eclipse中)的活动A使用Intent对象的putExtra定义了我想要发送到项目B中的活动B的对象。如果未定义通过Intent发送的此对象(项目B中的源代码),则存在NoClassDefFoundException。那么我可以使用方法setExtraClassloader来避免这种异常吗?如果是,我如何决定我必须通过哪个类加载器对象?我该如何正确实例化?

3 个答案:

答案 0 :(得分:12)

  

我读了一些关于的文件   类加载器,但我仍然不确定   他们需要的地点和原因。

一般来说,您不需要触摸类加载器系统。

  

在哪种情况下应该   开发人员实例化一个新的   类加载器?

经过大约十年的Java编程经验。 : - )

  

如果活动A位于   项目A(在Eclipse中)定义了一个   我想发送给的对象   项目B中的活动B使用putExtra   Intent对象。如果是这个对象   通过Intent发送的不是   定义(项目B中的源代码),   然后有一个   NoClassDefFoundException。所以我可以使用   方法setExtraClassloader为   避免这种例外?

不,因为项目A和项目B无法共享代码。把你需要的课程放在两个项目中。或者使用带有AIDL的远程服务接口,而不是Intents和附加功能。或者不要使用自定义类,而是将对象视为数据结构(例如,使用简单的HashMap Strings或其他内容。

答案 1 :(得分:9)

这是一个迟到的答案,但希望它会帮助其他人。

一般来说,类加载器用于在运行时加载可执行的Java代码。一个很好的例子就是从互联网上下载的插件。您可以从类文件中获取二进制数据,加载它,并根据需要调用其中的函数。当然,您需要使用调用程序已知的接口或抽象类,以便它知道如何使用该类。

当二进制类数据在典型庄园中无法访问时,使用自定义类加载器。例如,如果您的蓝牙设备包含带有实现接口的代码的类文件,则需要编写自定义类加载器以通过蓝牙接口加载类数据。

您可能想要编写自定义类加载器的另一个原因是,如果要更改加载的类访问其他类的方式。您可以限制加载的类可以访问哪些内部类,甚至可以编写自己的类,从而更改内部类的行为。例如,如果加载的类使用Java.io.File类,则可能需要强制它使用内部类以不同的方式访问文件。

简而言之,当您编写自定义类加载器时,您可以更改类的加载方式,以及加载的类如何加载所有其他类。

答案 2 :(得分:4)

ClassLoaders并不是那么难理解,至少在库存Java领域是这样。 (我可以在90分钟内教你ClassLoader系统 - 我在No Fluff Just Stuff节目中一直这样做。)这就是说,大多数时候你不需要创建自定义ClassLoader - 如果你想要的话在路上使用字节码的futz,java.lang.instrument是你的朋友。如果要从URL加载代码,请查看java.net.URLClassLoader。在这两者之间,对自定义ClassLoader的需求完全是零。