We don’t allow questions seeking recommendations for software libraries, tutorials, tools, books, or other off-site resources. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(8)
我发现了以下创建自定义类加载器的正当理由:
您想要从非常规源加载类(例如,一个类的字节码通过网络或 由 pidgeons 携带 0 和 1 - MessengerPidgeonClassLoader)。 API 中已经有一些针对此类情况的 ClassLoader 实现,例如 URLClassLoader。
您需要定义不同的层次结构来加载类。 ClassLoader 的默认实现首先将搜索委托给父级,然后它们尝试自己加载类。 也许您想要不同的层次结构。 这就是为什么 OSGI 和 Eclipse 有自己的类加载器,因为 Manifest .MF 文件定义了所有类型的奇怪层次路径(例如伙伴类加载)。 所有 Eclipse 类加载器都实现 BundleClassLoader 接口,并有一些额外的代码来查找 Eclipse 插件中的资源。
您需要对字节码进行一些修改。 也许字节码已加密,您将即时解密它(并不是说它确实有帮助,但已经尝试过)。 也许您想“修补”动态加载的类(JDO 字节码增强)。
如果您需要从内存中卸载类,或者加载可能在运行时更改其定义的类,则需要使用与系统类加载器不同的类加载器。 例如,典型的情况是应用程序从 XML 文件动态生成一个类,然后尝试重新加载该类。 一旦类位于系统类加载器中,就无法将其卸载并获得新的定义。
I found the following, valid reasons to create custom classloaders:
You want to load a class from an unconventional source (For example, the bytecode for one class is stored in a database, across the network or carried as 0 and 1s by pidgeons - MessengerPidgeonClassLoader). There is some ClassLoader implementations already in the API for such cases, such as URLClassLoader.
You need to define a different hierarchy to load classes. Default implementations of the ClassLoader delegate the search first to the parent, then they try to load the class themselves. Maybe you want a different hierarchy. This is the reason why OSGI and Eclipse have its own ClassLoaders as the Manifest .MF files define all types of weird hierarchy paths (buddy-classloading, for example). All Eclipse classloaders implement the BundleClassLoader interface and have some extra code to find resources within Eclipse Plugins.
You need to do some modification to the bytecode. Maybe the bytecode is encrypted, and you will unencrypt it on the fly (Not that it helps, really, but has been tried). Maybe you want to "patch" the classes loaded on the fly (A la JDO bytecode enhancement).
Using a different classloader than the System Classloader is required if you need to unload classes from memory, or to load classes than could change their definition at runtime. A typical case is an application that generates a class on the fly from an XML file, for example, and then tries to reload this class. Once a class is in the System Classloader, there is no way to unload it and have a new definition.
类加载器的常见用途是隔离 JAR。 如果您有一个使用插件的应用程序(Eclipse、Maven 2),那么你可能会遇到这种情况:插件 X 需要版本 1.0 的 jar A,而插件 Y 需要相同的 jar,但版本 2.0。 不过,X 不能与 2.0 版本一起运行。
如果您有类加载器,则可以创建类的分区(想象一下由细桥连接的孤岛;桥就是类加载器)。 这样,类加载器就可以控制每个插件可以看到的内容。
当插件 X 实例化具有静态字段的类 Foo 时,这没有问题,并且不会与插件 Y 中的“相同”类发生混淆,因为每个类加载器实际上都会创建自己的类 Foo 的实例。 然后,内存中就有两个类,其中
cl1.getName().equals(cl2.getName())
为true
,但cl1.equals(cl2)< /代码> 不是。 这意味着 cl1 的实例与 cl2 的实例分配不兼容。 这可能会导致奇怪的
ClassCastExceptions
,它表示org.project.Foo
无法分配给org.project.Foo
。就像偏远岛屿一样,这两个阶级并不知道另一个阶级的存在。 想想在不同岛屿上出生并长大的克隆人。 从 VM 的角度来看,没有问题,因为 Class 类型的实例像任何其他对象一样处理:可以有多个实例。 你认为其中一些是“相同的”对于虚拟机来说并不重要。
此模式的另一个用途是,您可以摆脱以这种方式加载的类:只需确保没有人拥有指向从类加载器加载的类创建的任何对象的指针,然后也忘记类加载器。 下次运行 GC 时,此类加载器加载的所有类都会从内存中删除。 这允许您“重新加载”应用程序,而无需重新启动整个虚拟机。
A common use of classloaders is to isolate a JAR. If you have an application which uses plugins (Eclipse, Maven 2), then you can have this situation: Plugin X needs jar A with version 1.0 while plugin Y need the same jar but version 2.0. X does not run with version 2.0, though.
If you have classloaders, you can create partitions of classes (think of isolated islands connected by thin bridges; the bridges are the classloaders). This way, the classloaders can control what each plugin can see.
When plugin X instantiates a class Foo, which has static fields, this is no problem and there won't be a mixup with the "same" class in plugin Y because each classloader will in fact create its own instance of the class Foo. You then have two classes in memory, where
cl1.getName().equals(cl2.getName())
istrue
butcl1.equals(cl2)
is not. This means that instances of cl1 are not assignment compatible to instances of cl2. This can lead to strangeClassCastExceptions
which say thatorg.project.Foo
can't be assigned toorg.project.Foo
.Just like with remote islands, the two classes are not aware that the other one exists. Think of human clones which are born and then raised on different islands. From the point of view of the VM, there is no problem because instances of the type Class are handled like any other object: There can be several of them. That you think that some of them are "the same" doesn't matter to the VM.
Another use for this pattern is that you can get rid of classes loaded this way: Just make sure that no one has a pointer to any object created from classes loaded from a classloader and then forget about the classloader, too. On the next run of the GC, all classes loaded by this classloader are removed from memory. This allows you to "reload" your application without having to restart the whole VM.
java 类加载器的另一个好链接 - Java 类加载器
Another good link for java class loaders - Java classloaders
我在过去写过一些关于使用委托后类加载器的博客:
A couple blogs I've written in the deep past about using post-delegation classloaders:
在这种情况下,你不能越过原始来源。 如果您真的想要内部的内容,硬核,请阅读Java 虚拟机规范的相关部分。
You can't go past the raw source, in cases like this. If you really want the inside dope, the hard core, read the relevant bits of the Java Virtual Machine Specification.
您需要创建自己的类加载器的情况极为罕见。 一般来说,如果您需要的话,您应该已经很好地理解了类加载器的作用。
换句话说,如果您问为什么需要创建自己的类加载器,那么您不需要创建一个;)
话虽如此,我还看到为处理密码学的应用程序创建了一个类加载器。 这样,每次创建 java.netSocket 或某种文件/流对象时,它不会使用 JVM 版本,而是使用它们自己的特殊自定义构建类。 这样他们就可以保证所有信息都经过加密并且不存在开发人员错误。
但这并不常见。 您可以从事整个 Java 职业生涯,而无需创建自己的自定义类加载器。 实际上,如果您需要创建一个,您应该真正询问是否有必要。
It's extremely rare that you need to create your own ClassLoader. And genereally if you need to, you should already have a really good understanding of what the ClassLoader does.
In other words, if you're asking why you would need to create your own ClassLoader, then you don't need to create one ;)
That being said, I've also seen a ClassLoader being created for an application that dealt with cryptography. This way every time you create a java.netSocket or some kind of file/stream object, instead of using the JVM versions it would use their own special custom built classes. This way they could guarantee the that all information was encrypted and that there were no developer errors.
But it's not very common. You can go a whole Java career without ever needing to create your own custom ClassLoader. Actually if you need to create one, you should really ask if it's necessary.
一个例子:
Tomcat 使用定制的 WebAppClassloader 来加载和隔离来自不同 Web 应用程序的类/jar。
An example:
Tomcat use customized WebAppClassloader to load and isolate classes/jars from different web applications.
根据应用程序的不同,开发人员可能会覆盖或完全替换类加载机制以满足他们的需求。
例如,我使用了一个应用程序,其类是从 LDAP 加载的:S
其他应用程序需要独立的类管理(就像大多数支持热部署的应用程序服务器一样)
。被列出。
Depending on the application, the developers might override or completely replace the class loading mechanism to suit their needs.
For instance, I have used one application whose classes are loaded from a LDAP :S
Other apps need independent class managing ( like most of the application servers that support hot-deploy )
About resources, there are TONS, in the web, that simply cannot be listed.