Jetty8.0.4的ClassLoader的体系结构

标签: Java | 发表时间:2012-04-20 18:19 | 作者:longhao
出处:http://www.longtask.com/blog

    1:JDK的ClassLoader基础

Bootstrap ClassLoader/启动类加载器 

主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作。

Extension ClassLoader/扩展类加载器 

主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。

System ClassLoader/系统类加载器 

主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。

User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类) 

在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。

 

自User Custom向Bootstrap的检查类是否已经加载;自Bootstrap向User Custom的尝试加载类

 //检查类是否被装载过
      Class c = findLoadedClass(name);
      //指定类未被装载过,自顶部向下的尝试加载类
       if (c ==  null) {
           try {
            //如果父类加载器不为空,指定为父类加载器加载

             if (parent !=  null) {

                c = parent.loadClass(name,  false);
            }  else {
                //在父类加载器为空的情况下,指定为系统启动类加载(native),不存在则返回null
                c = findBootstrapClassOrNull(name);
            }
          }  catch (ClassNotFoundException e) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }
             if (c ==  null) {
              // If still not found, then invoke findClass in order
              // to find the class.
              c = findClass(name); //通过自己的findClass来加载类
          }
      }
      if (resolve) {
          resolveClass(c);//用来做类链接操作
      }

     JVM在加载类时默认采用的是双亲委派机制。通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。关于虚拟机默认的双亲委派机制,我们可以从系统类加载器和标准扩展类加载器为例作简单分析。

 

     2:Jetty的classloader

2.1:Jetty的classloader架构

    web容器的classloader比普通java应用略为复杂。

    每个web上下文(web应用和war文件)的普通配置是有自身的classloader,系统的classloader是它的父类。这是普通的java classloader的层次,但是servlet规范提出了负责的层次要求:

1. 在WEB-INF/lib和WEB-INF/classes中包含的类的加载优先级高于父classloader中的类。这和普通的java2的classloader加载动作相反。

2. 像java.lang.String这样的系统类不会被WEB-INF/lib或者WEB-INF/classes中的类替代。不幸的是,servlet规范并没有清楚的规定哪些类是系统类,也没有清楚的指出javax类应该作为系统类

3. Server实现类应该对web应用和其他classloader不可见。不幸的是,servelt规范并没有规定什么是server class ,也没有清楚的指出像xerces parser 这样的common libraries应该作为实现类。

2.2:如何配置classloading

    jetty提供配置来控制以上三个选项。org.mortbay.jetty.webapp.WebAppContext.setParentLoaderPriority(boolean) 来控制所有类是否双亲委派的方式加载,这个配置解决了web应用加载的类在web应用和系统classpath同时存在的情况。

    org.mortbay.jetty.webapp.WebAppContext.setSystemClasses(String[])和org.mortbay.jetty.webapp.WebAppContext.setServerClasses(String[])用来控制那些能够被web应用看到或者覆写的类。

* SystemClasses 不能被webapp 上下文 classloaders覆写. 默认的是: 

{"java.","javax.servlet.","javax.xml.","org.mortbay.","org.xml.","org.w3c.", "org.apache.commons.logging.","org.eclipse.jetty.continuation.","org.eclipse.jetty.jndi.","org.eclipse.jetty.plus.jaas.","org.eclipse.jetty.websocket.WebSocket", "org.eclipse.jetty.websocket.WebSocketFactory", "org.eclipse.jetty.servlet.DefaultServlet"}

* ServerClasses (on the container classpath) 不能被webapp 上下文 classloaders看到但是可以被webapp覆写. 默认配置是: 

{"-org.eclipse.jetty.continuation.","-org.eclipse.jetty.jndi.", "-org.eclipse.jetty.plus.jaas.", "-org.eclipse.jetty.websocket.WebSocket","-org.eclipse.jetty.websocket.WebSocketFactory","-org.eclipse.jetty.servlet.DefaultServlet", "-org.eclipse.jetty.servlet.listener.", "org.eclipse.jetty."};

    [ 这段不知道如何翻译]Absolute classname can be passed, names ending with . are treated as packages names and names starting with – are treated as negative matches and must be listed before any enclosing packages.

      具体的类名可以不写,名称以.结尾代表是package名称,名称以"-"开头被认为是负面符号, and must be listed before any enclosing packages.

2.3:给jetty添加额外的classpaths

    在启动时,jetty会自动加载$jetty.home/lib下所有的jars,随之加载在start.jar中的文件start.config中明确配置的子目录(例如:$jetty.home/lib/management,$jetty.home/lib/naming/ 等)中的jars。所以,给jetty添加拓展的jars,需要在$jetty.home/lib/ext中创建一个任何你想的深度的文件层次。当然,你可以在自己创建start.config来定义默认加载动作来代替系统动作,否则,你需要使用以下方法:  

2.4:使用 jetty.class.path 系统属性

    如果你想添加一个类目录或者jar到jetty,但是你不想把东西放到$jetty.home/lib/ext/中,或者你不想自己创建start.config文件,你可以简单的使用系统属性-Djetty.class.path,示例:

    java -Djetty.class.path="../my/classes:../my/jars/special.jar:../my/jars/other.jar" -jar start.jar

2.5:在WebAppContext中使用extraClasspath()方法

    如果你因为某种原因不想把jars或者classes放到 $jetty.home/lib ,同事也不想放到WEB-INF/lib 或者 WEB-INF/classes中,你可以把它添加到 $JETTY_HOME/contexts/mycontext.xml 文件中

    <Configure class="org.mortbay.jetty.webapp.WebAppContext">

      …

      <Set name="extraClasspath">../my/classes:../my/jars/special.jar:../my/jars/other.jar</Set>

      …

2.6:使用惯用的WebAppClassLoader

   最后,没有其他替代方案满足你的需求,你可以在自己的webapp中定制classloader,建议你的classloader是    org.mortbay.jetty.webapp.WebAppClassLoader的子类,但这不是必须的。你可以像如下的方式配置自己的webapp的classloader:

     MyCleverClassLoader myCleverClassLoader = new MyCleverClassLoader();

     …

     WebAppContext webapp = new WebAppContext();

     …

     webapp.setClassLoader(myCleverClassLoader);

 

     参考资料:

相关 [jetty8 classloader 体系结构] 推荐:

java之classloader体系结构

- - 非技术 - ITeye博客
原文出处: http://www.iteye.com/topic/136427. a, Bootstrap ClassLoader/启动类加载器. 主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作.. b, Extension ClassLoader/扩展类加载器.

Jetty8.0.4的ClassLoader的体系结构

- - 龙浩的blog
    1:JDK的ClassLoader基础. Bootstrap ClassLoader/启动类加载器 . 主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作. Extension ClassLoader/扩展类加载器 . 主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作.

Java基础—ClassLoader的理解

- - ZJD'S NOTES
} ``` 其余两个ClassLoader都是继承自`ClassLoader`这个类. Java的类加载采用了一种叫做“双亲委托”的方式(稍后解释),所以除了`Bootstarp ClassLoader`其余的ClassLoader都有一个“父”类加载器, 不是通过集成,而是一种包含的关系. ``` ##“双亲委托” 所谓“双亲委托”就是当加载一个类的时候会先委托给父类加载器去加载,当父类加载器无法加载的时候再尝试自己去加载,所以整个类的加载是“自上而下”的,如果都没有加载到则抛出`ClassNotFoundException`异常.

Java ClassLoader原理分析

- - Java - 编程语言 - ITeye博客
一、JDK默认提供的三个ClassLoader. JDK 默认提供了如下几种ClassLoader. Bootstrp加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载 %JAVA_HOME%/jre/lib, -Xbootclasspath参数指定的路径以及 %JAVA_HOME%/jre/classes中的类.

深入浅出ClassLoader(译)

- - 并发编程网 - ifeve.com
你真的了解ClassLoader吗. 这篇文章翻译自zeroturnaround.com的 . Do You Really Get Classloaders? ,融入和补充了笔者的一些实践、经验和样例. 本文的例子比原文更加具有实际意义,文字内容也更充沛一些,非常感谢作者  Jevgeni Kabanov 能够共享如此优秀的文档.

classLoader卸载与jvm热部署 - redcreen

- - 博客园_redcreen的专栏
      以下的相关介绍都是在未使用dcevm的情况. classLoader的卸载机制.       jvm中没有提供class及classloader的unload方法.那热部署及osgi中是通过什么机制来实现的呢?实现思路主要是通过更换classLoader进行重新加载.之前的classloader及加载的class类在没有实例引用的情况下,在perm区gc的情况下会被回收掉..

JVM学习 - 体系结构

- - CSDN博客推荐文章
一:Java技术体系模块图. 二:JVM运行时内存区域模型. 也称"永久代” 、“非堆”,  它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域. 可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小. 运行时常量池:是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中.

【Oracle】物理体系结构

- - CSDN博客推荐文章
一、ORACLE 物理体系结构. PGA: 私有内存区,仅供当前发起用户使用. 用户登录后的session信息会保存在PGA. 执行排序,如果内存不够,oracle会在临时表空间中完成. SGA: 包含共享池,数据缓冲区,日志缓冲区以及一些相关的进程. DATABASE: 数据最终存放的地方,其中一块区域是日志存放区.

Java类加载器classLoader的工作机制

- - CSDN博客推荐文章
类加载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件. 在Java中,类转载器把一个类装入JVM中,需要经过以下步骤:. 1.装载:查找和导入Class文件. 2.链接: 执行校验、准备和解析步骤,其中解析步骤是可以选择的:. a)校验: 检查载入Class文件数据的正确性;. b)准备:给类的静态变量分配存储空间;.

计算机网络体系结构

- - CSDN博客推荐文章
OSI/RM 开放系统互连参考模型. OSI/RM 与TCP/IP参考模型的比较. 开放式系统互连基本参考模型是由国际标准化组织(ISO)指定的. OSI包括了体系结构,服务定义和协议规范三级抽象. 注意OSI参考模型并非具体实现的描述,它只是一个为制定标准而提供的概念性框架. 在OSI中,只有各种协议是可以实现的,网络中的设备只有与OSI的有关协议相一致时才能互连.