`
csbison
  • 浏览: 153494 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

关于ClassLoader

阅读更多

Java本身是一种设计的非常简单,非常精巧的语言,所以Java背后的原理也很简单,归结起来就是两点:

 

1JVM的内存管理

 

理解了这一点,所有和对象相关的问题统统都能解决

 

2JVM Class Loader

 

理解了这一点,所有和Java相关的配置问题,包括各种App Server的配置,应用的发布问题统统都能解决

 

App Class Loader

|----- EJB Class Loader

|----- Web App Class Loader

 

如果在App Class Loader级别配置,是全局可见的。如果打包在EJB里面,那么就不会影响到Web Application,反之亦然,如果你在WEB-INF下面放置Hibernate,也不会影响到EJB。放在EJB Class Loader或者放在Web App Class Loader级别主要就是在局部范围内有效,不影响到其它的应用。

 

试想,如果在一个Weblogic上面配置多个虚拟域,你使用www.bruce.com域名,开发你的网站,我使用www.fankai.com开发我的网站,那么当然不希望我们的Hibernate相互干扰,所以就可以放在 EJB Class Loader级别来配置Hibernate

 

进一步阐述一下EJB Class Loader的问题:

 

先再次强调一下,HibernateEJB,和App Server不存在兼容性问题,他们本来就是不相关的东西,就好像JDBC,相信没有人会认为JDBCEJB不兼容吧,Hibernate也是一样,它只和JDBC驱动,和数据库有兼容性问题,而和EJB,和App Server完全是不搭界的两回事。凡是认为HibernateEJB不兼容的人,其实是都是因为对EJB学习的不到家,把责任推到Hibernate身上了。

 

我前面提到过Class Loader的层次,这里不重复了,总之我们先来看看Class Loader的作用范围:

 

((Boot Strap)) Class Loader:

load JRE\lib\rt.jar, sunrsasign.jar, charsets.jar, jce.jar, jsse.jar, plugin.jar

Ext Class Loader:

load JRE\lib\ext目录下的库文件, load JRE\classes目录下的类

App Class Loader:

load CLASSPATH变量指定路径下的类

 

以上的load路径都是写死在JVMC++源代码里面的,不能改变,详细请见王森的《Java深度历险》

 

在一个特定的App Server上,Class Loader会继续向下继承,继承的层次会根据不同的App Server有所不同,但是肯定不会变的就是:

 

EJB Class Loader:

 

继承自App Class Loader,继承层次根据App Server有所不同,一个EJB Class Loader它的load Class的范围仅限于JAR或者EAR范围之内。

 

Web App Class Loader:

 

继承自App Class Loader,继承层次根据App Server有所不同,一个Web App Class Loader:它的load Class的范围在 WEB-INF\lib下的库文件和WEB-INF\classes目录下的class文件。

 

Web App Class Loader很好理解,大家毕竟用的很多,App Server上的一个Web Application会创建一个Web App Class Loader的实例去负责load class,所以如果你想让Hibernate只在这个Web Application内生效,把它放到WEB-INF\lib下去就好了。

 

如果你把Hibernate放到了CLASSPATH变量指定的路径下,而你在WEB-INF\lib也放了一份,那么Web App Class Loader由于load范围所限,它会首先找到WEB-INF\lib下的那份Hibernate,按照它的配置来初始化Hibernate

 

如果你把Hibernate放到了CLASSPATH变量指定的路径下,但你在WEB-INF\lib什么都没有放,那么Web App Class Loader由于load范围所限,它根本什么都找不到,于是它把load Hibernate的责任交给上一级的Class Loader,这样直到App Class Loader,它找到了Hibernate,按照它的配置来初始化Hibernate

 

EJB Class Loader稍微复杂一点,不那么容易理解。App Server会针对每一个EJB包文件创建一个EJB Class Loader的实例,例如:

 

((Hello Robbin)).jar

((Hello Bruce)).jar

 

当你把这两个jar发布到App Server上以后,会创建两个EJB Class Loader的实例,分别去load这两个EJB包,比如说:

 

CLEJB_Robbinload ((Hello Robbin)).jar

CLEJB_Bruceload ((Hello Bruce)).jar

 

那么CLEJB_Robbinload范围就仅仅限于HelloRobbin.jar之内,它load不到HelloRobbin.jar之外的任何文件,当然它也load不到HelloBruce.jar

 

说到这里,我相信大家应该已经明白为什么EJB规范不允许EJBIO操作了吧?因为EJB Class Loader根本找不到jar包之外的文件!!!

 

如果现在你想实现HelloRobbin.jarHelloBruce.jar的互相调用,那么该怎么办?他们使用了不同的EJB Class Loader,相互之间是找不到对方的。解决办法就是使用EAR

 

现在假设HelloRobbin.jarHelloBruce.jar都使用了Hibernate,看看该怎么打包和发布:

 

HelloEJB.ear

 

|------ ((Hello Robbin)).jar

|------ ((Hello Bruce)).jar

|------ Hibernate2.jar

|------ pojo.jar (定义所有的持久对象和hbm文件的jar)

|------ cglib-asm.jar

|------ commons-beanutils.jar

|------ commons-collections.jar

|------ commons-lang.jar

|------ commons-logging.jar

|------ dom4j.jar

|------ odmg.jar

|------ log4j.jar

|------ jcs.jar

|------ Hibernate.properties

|------ log4j.properties

|------ cache.ccf

|------ META-INF\application.xml (J2EE规范的要求,定义EAR包里面包括了哪几个EJB)

 

除此之外,按照EJB规范要求,HelloRobbin.jarHelloBruce.jar还必须指出调用jar包之外的类库的名称,这需要在jar包的manifest文件中定义:

 

((Hello Robbin)).jar

|------ META-INF\MANIFEST.MF

 

MANIFEST.MF中必须包括如下一行:

 

Class-Path: log4j.jar hibernate2.jar cglib-asm.jar commons-beanutils.jar commons-collections.jar commons-lang.jar

commons-logging.jar dom4j.jar jcs.jar odmg.jar jcs.jar pojo.jar

 

这样就OK了,当把HelloEJB.ear发布到App Server上以后,App Server创建一个EJB Class Loader实例load EAR包里面的EJB,再根据EJBjar包里面的MANIFEST.MF指出的Class-Path去寻找相应的jar包之外的类库。

 

所以一个EAR包有点类似一个Web ApplicationEJB Class Loaderload范围也就是EAR范围之内,它load不到EAR之外的文件。除非把Hibernate定义到CLASSPATH指定的路径下,在这种情况下,EJB Class Loader找不到Hibernate,只能交给上一级的Class Loader,最后由App Class Loader找到Hibernate,进行初始化。

 

由于EAR这样load Class规则,假设RobbinBruce都在同一个Weblogic上运行自己的网站,而我们都不希望自己的程序里面的Hibernate配置被对方的搞乱掉,那么我们就可以这样来做:

 

Robbin's Website:

 

Robbin.ear

 

|-------- robbin.war (Web Application打包)

|-------- robbin.jar (把开发的EJB打包)

|-------- Hibernate2.jar

..........................

|-------- META-INF\application.xml

 

Bruce's Website:

 

Bruce.ear

|-------- bruce.war (Web Application打包)

|-------- bruce.jar (把开发的EJB打包)

|-------- Hibernate2.jar

..........................

|-------- META-INF\application.xml

 

这样在同一个App Server上运行,就可以互相不干扰。

 

#################################################

richardluo 发表自dev2dev@bea

 

了解ClassLoader

1 什么是 ClassLoader?

Java 程序并不是一个可执行文件,是需要的时候,才把装载到 JVM中。ClassLoader 做的工作就是 JVM 中将类装入内存。 而且,Java ClassLoader 就是用 Java 语言编写的。这意味着您可以创建自己的 ClassLoader

ClassLoader 的基本目标是对类的请求提供服务。当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 试图返回一个表示这个类的 Class 对象。 通过覆盖对应于这个过程不同阶段的方法,可以创建定制的 ClassLoader

2 一些重要的方法

A) 方法 loadClass

ClassLoader.loadClass() ClassLoader 的入口点。该方法的定义如下:

Class loadClass( String name, boolean resolve ;

name JVM 需要的类的名称,如 Foo java.lang.Object

resolve 参数告诉方法是否需要解析类。在准备执行类之前,应考虑类解析。并不总是需要解析。如果 JVM 只需要知道该类是否存在或找出该类的超类,那么就不需要解析。

 

B) 方法 defineClass

defineClass 方法是 ClassLoader 的主要诀窍。该方法接受由原始字节组成的数组并把它转换成 Class 对象。原始数组包含如从文件系统或网络装入的数据。defineClass 管理 JVM 的许多复杂、神秘和倚赖于实现的方面 -- 它把字节码分析成运行时数据结构、校验有效性等等。不必担心,您无需亲自编写它。事实上,即使您想要这么做也不能覆盖它,因为它已被标记成final的。

 

C) 方法 findSystemClass

findSystemClass 方法从本地文件系统装入文件。它在本地文件系统中寻找类文件,如果存在,就使用 defineClass 将原始字节转换成 Class 对象,以将该文件转换成类。当运行 Java 应用程序时,这是 JVM 正常装入类的缺省机制。(Java 2 ClassLoader 的变动提供了关于 Java 版本 1.2 这个过程变动的详细信息。) 对于定制的 ClassLoader,只有在尝试其它方法装入类之后,再使用 findSystemClass。原因很简单:ClassLoader 是负责执行装入类的特殊步骤,不是负责所有类。例如,即使 ClassLoader 从远程的 Web 站点装入了某些类,仍然需要在本地机器上装入大量的基本 Java 库。而这些类不是我们所关心的,所以要 JVM 以缺省方式装入它们:从本地文件系统。这就是 findSystemClass 的用途。

 

D) 方法 resolveClass

正如前面所提到的,可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的 loadClass 时,可以调用 resolveClass,这取决于 loadClass resolve 参数的值。

 

 

E) 方法 findLoadedClass

findLoadedClass 充当一个缓存:当请求 loadClass 装入类时,它调用该方法来查看 ClassLoader 是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。应首先调用该方法。

 

3 怎么组装这些方法

1 调用 findLoadedClass 来查看是否存在已装入的类。

2 如果没有,那么采用那种特殊的神奇方式来获取原始字节。

3 如果已有原始字节,调用 defineClass 将它们转换成 Class 对象。

4 如果没有原始字节,然后调用 findSystemClass 查看是否从本地文件系统获取类。

5 如果 resolve 参数是 true,那么调用 resolveClass 解析 Class 对象。

6 如果还没有类,返回 ClassNotFoundException

 

4Java 2 ClassLoader 的变动

1loadClass 的缺省实现

定制编写的 loadClass 方法一般尝试几种方式来装入所请求的类,如果您编写许多类,会发现一次次地在相同的、很复杂的方法上编写变量。 Java 1.2 loadClass 的实现嵌入了大多数查找类的一般方法,并使您通过覆盖 findClass 方法来定制它,在适当的时候 findClass 会调用 loadClass 这种方式的好处是您可能不一定要覆盖 loadClass;只要覆盖 findClass 就行了,这减少了工作量。

 

2)新方法:findClass

loadClass 的缺省实现调用这个新方法。findClass 的用途包含您的 ClassLoader 的所有特殊代码,而无需要复制其它代码(例如,当专门的方法失败时,调用系统 ClassLoader)。

 

3 新方法:getSystemClassLoader

如果覆盖 findClass loadClassgetSystemClassLoader 使您能以实际 ClassLoader 对象来访问系统 ClassLoader(而不是固定的从 findSystemClass 调用它)。

 

4 新方法:getParent

为了将类请求委托给父代 ClassLoader,这个新方法允许 ClassLoader 获取它的父代 ClassLoader。当使用特殊方法,定制的 ClassLoader 不能找到类时,可以使用这种方法。

父代 ClassLoader 被定义成创建该 ClassLoader 所包含代码的对象的 ClassLoaderCo

分享到:
评论

相关推荐

    关于Classloader的总结!loadClass的分析和加载细节的分析

    在Java编程语言中,`Classloader`(类加载器)是一个至关重要的组件,它负责将类的`.class`文件从磁盘加载到JVM(Java虚拟机)内存中,使得程序能够执行。这篇博文主要围绕`Classloader`的`loadClass`方法进行深入...

    ClassLoader运行机制 自己写的

    在Java虚拟机(JVM)中,类加载器(ClassLoader)是至关重要的组成部分,它负责查找和加载类的字节码文件。理解ClassLoader的工作机制对于深入掌握Java应用程序的运行至关重要。这里我们将详细讨论ClassLoader的运行...

    classloader

    Java ClassLoader是Java运行时系统的关键但经常被忽视的组件,负责在运行时查找和加载类文件。通过创建自定义ClassLoader,你可以定制JVM,使类文件的引入方式完全重新定义,这提供了很多实用和有趣的可能。这篇教程...

    ClassLoader

    ### Java虚拟机中ClassLoader概述与双亲委托机制详解 #### 一、ClassLoader概念与作用 在Java编程语言中,`ClassLoader`是一个非常重要的组件,它负责加载程序运行所需的类文件到Java虚拟机(JVM)中。`ClassLoader`...

    661.659.JAVA基础教程_动态代理与Java8新特性-复习:ClassLoader(661).rar

    在本教程中,我们将深入探讨Java编程语言中的两个核心概念:动态代理和Java 8的新特性,特别是关于ClassLoader的部分。动态代理是Java中一个强大的工具,它允许在运行时创建对象,这些对象可以作为其他对象的代理,...

    自定义classloader的使用

    在Java中,Classloader是加载类的关键组件,它负责查找、加载和初始化字节码文件。自定义Classloader允许开发者根据特定需求定制类的加载逻辑,例如加密类文件、隔离不同版本的库或者动态加载代码。本文将深入探讨...

    Java ClassLoader定制实例

    在Java编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中。理解ClassLoader的工作原理以及如何定制它,对于深入学习Java的运行机制和进行高级应用开发具有重要意义。本篇文章将...

    ClassLoader小例子

    在Java编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。本示例"ClassLoader小例子"将深入探讨这个概念,并通过一个具体的程序来演示其工作原理。下面我们...

    java ClassLoader机制及其在OSGi中的应用

    Java ClassLoader机制是Java虚拟机(JVM)中一个至关重要的组成部分,它的主要任务是将类的.class文件加载到JVM中,使得程序能够运行。ClassLoader不仅负责类的加载,还涉及类的验证、初始化等一系列过程。理解...

    深入理解ClassLoader工作机制.docx

    《深入理解ClassLoader工作机制》 Java虚拟机(JVM)中的ClassLoader是负责加载类到内存中的核心组件。它不仅承担着将字节码转换为可执行对象的重任,还参与了类生命周期的各个阶段,包括加载、验证、准备、解析、...

    JVM ClassLoader简析

    首先,ClassLoader可以分为三种基本类型:Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader。Bootstrap ClassLoader是JVM启动时的第一个ClassLoader,负责加载JDK的`<JAVA_HOME>\lib`目录下...

    java classloader

    通过这些文档,你可以获得关于Java ClassLoader的全面理解,包括它的作用、工作流程、如何自定义以及它在整个Java生态系统中的位置。学习这些知识对于提升你的Java编程技能,尤其是开发复杂和动态的应用程序时,是...

    ClassLoader 详解.doc

    《ClassLoader详解》 Java应用程序的运行离不开类的加载,而ClassLoader正是这个过程的关键角色。它负责将类的字节码加载到Java虚拟机(JVM)中并转换为可执行的Java对象。深入理解ClassLoader的工作原理对于优化...

    理解Java ClassLoader机制

    Java ClassLoader机制是Java运行时环境中的核心组件之一,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。理解ClassLoader的工作原理对于优化应用性能、处理类加载问题以及实现自定义加载器至关重要。 首先...

    破解java加密的ClassLoader.java,在classloader植入破解代码

    破解java加密的ClassLoader.java,在classloader植入破解代码

    ClassLoader 案例

    在Java编程语言中,ClassLoader是核心组件之一,它负责加载类到JVM(Java虚拟机)中。自定义ClassLoader允许开发者根据特定需求加载类,比如动态加载或更新类文件,这在某些高级应用场景中非常有用,如插件系统、热...

    ClassLoader类加载机制和原理详解

    在Java编程语言中,ClassLoader是核心组件之一,它负责加载类到JVM(Java虚拟机)中执行。本文将深入探讨ClassLoader的工作原理和类加载机制,帮助开发者理解这个至关重要的概念。 1. 类加载机制概述 Java的类加载...

    ClassLoader的 一些测试

    在Java编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中执行。这篇测试主要探讨了ClassLoader的工作原理及其在实际应用中的使用。通过阅读给出的博文链接,我们可以深入理解...

Global site tag (gtag.js) - Google Analytics