有人能给我一个很好的资源或者解释一下Class Loaders背后的概念吗?我在类加载器上找到了以下资源http://www.onjava.com/lpt/a/5586但仍然没有帮助.以下问题可能看起来很愚蠢,但试图回答它们总是让我感到困惑.
为什么开发人员编写Custom类加载器,为什么不调用Bootstrap类加载器来调用自定义类呢?有什么需要定义自定义类加载器?
为什么有这么多种类的装载机?例如:Bootsrap,Comman,Catalina类装载机等,
提前致谢.
Mario Ortegó.. 45
我找到了以下有效创建自定义类加载器的原因:
您希望从非常规源加载类(例如,一个类的字节码存储在数据库中,跨网络或由pidgeons作为0和1进行 - MessengerPidgeonClassLoader).对于此类情况,API中已存在一些ClassLoader实现,例如URLClassLoader.
您需要定义不同的层次结构来加载类.ClassLoader的默认实现首先将搜索委托给父级,然后他们尝试自己加载该类.也许你想要一个不同的等级.这就是为什么OSGI和Eclipse有自己的ClassLoaders作为Manifest .MF文件定义所有类型的奇怪层次路径(例如,伙伴类加载)的原因.所有Eclipse类加载器都实现了BundleClassLoader接口,并有一些额外的代码来查找Eclipse插件中的资源.
您需要对字节码进行一些修改.也许字节码是加密的,你会动态解密它(不是它有帮助,真的,但已经尝试过).也许你想要"修补"动态加载的类(一个JDO字节码增强).
如果需要从内存中卸载类,或者加载类而不是在运行时更改其定义,则需要使用与System Classloader不同的类加载器.典型的情况是,例如,从XML文件动态生成类的应用程序,然后尝试重新加载此类.一旦类在System Classloader中,就无法卸载它并拥有新的定义.
我找到了以下有效创建自定义类加载器的原因:
您希望从非常规源加载类(例如,一个类的字节码存储在数据库中,跨网络或由pidgeons作为0和1进行 - MessengerPidgeonClassLoader).对于此类情况,API中已存在一些ClassLoader实现,例如URLClassLoader.
您需要定义不同的层次结构来加载类.ClassLoader的默认实现首先将搜索委托给父级,然后他们尝试自己加载该类.也许你想要一个不同的等级.这就是为什么OSGI和Eclipse有自己的ClassLoaders作为Manifest .MF文件定义所有类型的奇怪层次路径(例如,伙伴类加载)的原因.所有Eclipse类加载器都实现了BundleClassLoader接口,并有一些额外的代码来查找Eclipse插件中的资源.
您需要对字节码进行一些修改.也许字节码是加密的,你会动态解密它(不是它有帮助,真的,但已经尝试过).也许你想要"修补"动态加载的类(一个JDO字节码增强).
如果需要从内存中卸载类,或者加载类而不是在运行时更改其定义,则需要使用与System Classloader不同的类加载器.典型的情况是,例如,从XML文件动态生成类的应用程序,然后尝试重新加载此类.一旦类在System Classloader中,就无法卸载它并拥有新的定义.
类加载器的一个常见用途是隔离JAR.如果您有一个使用插件的应用程序(Eclipse,Maven 2),那么您可以遇到这种情况:插件X需要jar A版本1.0,而插件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时,此类加载器加载的所有类都将从内存中删除.这允许您"重新加载"应用程序,而无需重新启动整个VM.