java 正确使用 Classloader(尤其是在 Android 中)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2799225/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Correct use of Classloader (especially in Android)
提问by CommonsWare
I read some documentations about classloaders, but im still not sure where and why they are needed. The Android API says:
我阅读了一些关于类加载器的文档,但我仍然不确定在哪里以及为什么需要它们。Android API 说:
Loads classes and resources from a repository. One or more class loaders are installed at runtime. These are consulted whenever the runtime system needs a specific class that is not yet available in-memory.
从存储库加载类和资源。在运行时安装一个或多个类加载器。每当运行时系统需要内存中尚不可用的特定类时,就会查阅这些。
So if i understand this correct, there can be many classlaoders which are responsible for loading new classes. But how the system decides which to use? And in which situation should a developer instantiate a new classloader?
因此,如果我理解正确,则可能有许多负责加载新类的类加载器。但是系统如何决定使用哪个?在什么情况下开发人员应该实例化一个新的类加载器?
In the Android API for Intent there is a method
在 Android API for Intent 中有一个方法
public void setExtrasClassLoader (ClassLoader loader)
The description says:
描述说:
Sets the ClassLoader that will be used when unmarshalling any Parcelable values from the extras of this Intent.
设置在从此 Intent 的 extras 解组任何 Parcelable 值时将使用的 ClassLoader。
So can i define there a special classloader so that i can pass object with an Intent which are not defined in the receiving activity? An example:
那么我可以在那里定义一个特殊的类加载器,以便我可以传递带有未在接收活动中定义的 Intent 的对象吗?一个例子:
If activity A which is located in Project A (in Eclipse) defines an object which i want to send to Activity B in Project B using putExtra of the Intent object. If this object which is send over the Intent is not defined (source code in project B), then there is a NoClassDefFoundException. So can i use the method setExtraClassloader to avoid this exception? If yes, how can i decide which classloader object i have to pass? And how do I instantiate it correctly?
如果位于项目 A(在 Eclipse 中)的活动 A 定义了一个对象,我想使用 Intent 对象的 putExtra 将其发送到项目 B 中的活动 B。如果未定义通过 Intent 发送的此对象(项目 B 中的源代码),则存在 NoClassDefFoundException。那么我可以使用 setExtraClassloader 方法来避免这个异常吗?如果是,我如何决定我必须通过哪个类加载器对象?以及如何正确实例化它?
回答by CommonsWare
I read some documentations about classloaders, but im still not sure where and why they are needed.
我阅读了一些关于类加载器的文档,但我仍然不确定在哪里以及为什么需要它们。
Generally speaking, you do not need to touch the classloader system.
一般来说,你不需要接触类加载器系统。
And in which situation should a developer instantiate a new classloader?
在什么情况下开发人员应该实例化一个新的类加载器?
After about a decade's experience in Java programming. :-)
经过大约十年的 Java 编程经验。:-)
If activity A which is located in Project A (in Eclipse) defines an object which i want to send to Activity B in Project B using putExtra of the Intent object. If this object which is send over the Intent is not defined (source code in project B), then there is a NoClassDefFoundException. So can i use the method setExtraClassloader to avoid this exception?
如果位于项目 A(在 Eclipse 中)的活动 A 定义了一个对象,我想使用 Intent 对象的 putExtra 将其发送到项目 B 中的活动 B。如果未定义通过 Intent 发送的此对象(项目 B 中的源代码),则存在 NoClassDefFoundException。那么我可以使用 setExtraClassloader 方法来避免这个异常吗?
No, because Project A and Project B cannot share code. Put the class you need in both projects. Or use a remote service interface with AIDL instead of Intentsand extras. Or do not use a custom class, but rather treat the object as a data structure (e.g., use a simple HashMapof Stringsor something).
不可以,因为项目 A 和项目 B 不能共享代码。将您需要的课程放在两个项目中。或者使用带有 AIDL 的远程服务接口,而不是Intents附加功能。或者不使用自定义类,而是将对象视为数据结构(例如,使用简单HashMap的Strings或某物)。
回答by Mick
This is a late answer, but hopefully it will help others.
这是一个迟到的答案,但希望它会帮助其他人。
Classloaders in general, are used to load executable Java code at runtime. A good example of this would be a plugin that is downloaded from the internet. You can take the binary data from a class file, load it, and call the functions within it as needed. You do, of course, need to use an interface or abstract class that's known by the calling program so it knows how to use the class.
类加载器通常用于在运行时加载可执行的 Java 代码。从 Internet 下载的插件就是一个很好的例子。您可以从类文件中获取二进制数据,加载它,并根据需要调用其中的函数。当然,您确实需要使用调用程序已知的接口或抽象类,以便它知道如何使用该类。
A custom classloader is used when the binary class data isn't accessible in a typical manor. For instance, if you have a bluetooth device that contains a class file with code implementing an interface, you would need to write a custom classloader to load the class data over the bluetooth interface.
当二进制类数据在典型的庄园中不可访问时,使用自定义类加载器。例如,如果您的蓝牙设备包含一个带有实现接口的代码的类文件,您将需要编写一个自定义类加载器来通过蓝牙接口加载类数据。
Another reason you may want to write a custom classloader is if you want to change how the loaded class accesses other classes. You can restrict which internal classes the loaded class has access to or even write your own classes, changing the behavior of an internal class. For instance, if the loaded class uses the Java.io.File class, you may need to force it to use an internal class to access files in a different way.
您可能想要编写自定义类加载器的另一个原因是,如果您想更改加载的类访问其他类的方式。您可以限制加载的类可以访问哪些内部类,甚至可以编写自己的类,从而更改内部类的行为。例如,如果加载的类使用 Java.io.File 类,您可能需要强制它使用内部类以不同的方式访问文件。
In short, when you write a custom classloader, you change how a class is loaded, as well as how the loaded class will load all other classes.
简而言之,当您编写自定义类加载器时,您会更改类的加载方式,以及加载的类将如何加载所有其他类。
回答by Ted Neward
ClassLoaders aren't all that hard to understand, at least in the stock Java space. (I can teach you the ClassLoader system in 90 minutes--I do it all the time at the No Fluff Just Stuff shows.) That said, most of the time you don't need to create a custom ClassLoader--if you want to futz with bytecode on the way in, java.lang.instrument is your friend. If you want to load code from a URL, check out java.net.URLClassLoader. Between those two, the need for a custom ClassLoader is entirely nil.
类加载器并不难理解,至少在股票 Java 领域是如此。(我可以在 90 分钟内教你 ClassLoader 系统——我一直在 No Fluff Just Stuff 节目中这样做。)也就是说,大多数时候你不需要创建自定义类加载器——如果你愿意的话在进入的过程中使用字节码进行 futz,java.lang.instrument 是您的朋友。如果要从 URL 加载代码,请查看 java.net.URLClassLoader。在这两者之间,对自定义 ClassLoader 的需求完全为零。

