`

javaClassLoader类加载器详解<转>

阅读更多
由于一个JDBC的基本封装引来众多砖块,其实对本人来说是好事!毕竟能够学到点东西。由于在使用到Class.forName()方法,就进而对Class Loader有了疑惑,因此查阅了一些资料,这里来进行个人学习的总结。不过如果有建议或者拍砖。本人非常感谢!

  下面是我对Class Loader进行一点总结

在Java中,类的实例化流程分为两个部分:类的加载和类的实例化。类的加载分为显式加载和隐式加载。大家都知道使用new关键字创建类实例,那么new其实属于隐式地包含了类的加载过程。那么什么又是显式的加载呢?其实Class.forName就是一个最常用的。不管隐式还是显式都是通过调用ClassLoader类的loadClass方法来完成类的实际加载工作。但是如果直接调用ClassLoader的loadClass方法是一种不常见的显式加载类的技术。但是现在也在一些框架中使用了。

这样看起来好像ClassLoade没什么内涵。但是细心去研究发现其实Java类加载器是有层次的。ClassLoader在加载类时有一定的层次关系和规则。在Java中,有四种类型的加载器,分别是 Bootstrap class loader、Extensions class loader、System class loader以及用户自定义的类加载器。现在来看看上面四种类型的加载器的职责。

引用

1. Bootstrap Class loader:该类加载器层次结构的最高层,直接负责<JAVA_HOME>/lib目录下的的核心API或-Xbootclasspath选项指定的jar包。

2. Extensions Class Loader:该类主要负责默认为<JAVA_HOME>/lib/ext目录或者-Djava.ext.dirs指定目录下的jar包加载。

3. System class loader:主要负责加载路径为java.class.path,默认为环境变量CLASSPATH中设定的值。

4. 用户自定义的类加载:根据用户的需要定制自己的类加载过程,在运行期进行指定类的动态实时加载。


大致就这四种那个类的加载。问题是他们有层次。看看他们在加载过程:
加载类的顺序:

引用

Bootstrap Class loader --> Extensions Class Loader -->System class loader ---->用户自定义的类加载;他们都是在直接的加载路径上进行加载。


对类是否加载过进行判断的过程则是加载类的逆序。

每个类加载器都有直接的名字空间,对于同一个类加载器实例来说,名字相同的类只能存在一个,并且仅仅加载一次。不管该类有没有变化,下次再需要加载时候,它只是从自己的缓存中直接返回已经加载过的类引用。我们自己编写的类默认情况下都是通过System ClassLoader进行加载的。当我们使用new关键字或者class.forName来加载类时,所有加载的类则调用SystemClassLoader进行加载。
通过上面的分析大概知道了一点类的加载机制了吧。以及各自的加载路径。

引用

设想:
  既然知道我们知道类的加载机制和不同加载路径。我们是否会想到一个这样的问题。就是我们常常用SVN类纪录代码的版本。我们能不能利用类的加载机制来尝试加载一个类的不同版本的共存呢?利用不同类的加载机制和类加载机制的路径来加载该类的另外一个不同的版本呢?因此为了充分发挥用户自定义类加载机制,以下将试试利用自己的类加载器,对类的过程进行加载和控制和管理。



实施步骤:
1. 编写自定义的类加载
      分析得出编写自定义的类加载器,必须要去继承ClassLoader。
Java代码
import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.IOException;  
import java.util.HashSet;  
 
/** 
* Description: 1. 要实现同一个类的不同版本的共存,那么这些不同版本必须有不同的类加载器进行加载 
*              2. 不能采用默认的加载器来进行加载类 
* @author Developer 
*/ 
public class CustomerClassLoader extends ClassLoader {  
    private String basedir; //需要该类加载器直接加载的类文件的基目录  
    private HashSet dynaclazz; //需要由该类加载器直接加载的类名  
      
    public CustomerClassLoader(String basedir,String[] clazz) throws IOException{  
        super(null);//防止父类进行加载  
        this.basedir = basedir;  
        dynaclazz = new HashSet();  
        loadClassByMe(clazz);  
    }  
      
    /** 
     *  
     * @param clazns 
     * @throws IOException  
     */ 
    private void loadClassByMe(String[] clazns) throws IOException{  
        for(int i=0;i<clazns.length ; i++){  
            loadDirectly(clazns[i]);  
            dynaclazz.add(clazns[i]);  
        }  
    }  
    
      
     /** 
      *  
      * @param name 
      * @return 
     * @throws IOException  
      */ 
    private Class loadDirectly(String name) throws IOException {  
       Class cls = null;  
       StringBuffer sb = new StringBuffer(basedir);  
       String classname = name.replace('.', File.separatorChar)+".class";  
       sb.append(File.separator + classname);  
       File classF = new File(sb.toString());  
       cls = instantiateClass(name,new FileInputStream(classF),classF.length());  
       return cls;  
    }  
      
    /** 
     *  
     * @param name 
     * @param fileInputStream 
     * @param len 
     * @return 
     * @throws IOException 
     */ 
 
    private Class instantiateClass(String name,  
            FileInputStream fileInputStream, long len) throws IOException {  
          byte[] raw = new byte[(int)len];  
          fileInputStream.read(raw);  
          fileInputStream.close();  
        return  defineClass(name,raw,0,raw.length);  
    }  
      
    protected Class loadClass(String name,boolean resolve)throws ClassNotFoundException{  
        Class cls = null;  
        cls = findLoadedClass(name);  
         if(!this.dynaclazz.contains(name) && cls == null)  
             cls = getSystemClassLoader().loadClass(name);  
         if(cls == null)  
             throw new ClassNotFoundException(name);  
         if(resolve)  
             resolveClass(cls);  
        return cls;  
          
    }  


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashSet;

/**
* Description: 1. 要实现同一个类的不同版本的共存,那么这些不同版本必须有不同的类加载器进行加载
*              2. 不能采用默认的加载器来进行加载类
* @author Developer
*/
public class CustomerClassLoader extends ClassLoader {
private String basedir; //需要该类加载器直接加载的类文件的基目录
private HashSet dynaclazz; //需要由该类加载器直接加载的类名

public CustomerClassLoader(String basedir,String[] clazz) throws IOException{
super(null);//防止父类进行加载
this.basedir = basedir;
dynaclazz = new HashSet();
loadClassByMe(clazz);
}

/**
*
* @param clazns
* @throws IOException
*/
private void loadClassByMe(String[] clazns) throws IOException{
for(int i=0;i<clazns.length ; i++){
loadDirectly(clazns[i]);
dynaclazz.add(clazns[i]);
}
}
 

/**
  *
  * @param name
  * @return
* @throws IOException
  */
private Class loadDirectly(String name) throws IOException {
       Class cls = null;
       StringBuffer sb = new StringBuffer(basedir);
       String classname = name.replace('.', File.separatorChar)+".class";
       sb.append(File.separator + classname);
       File classF = new File(sb.toString());
       cls = instantiateClass(name,new FileInputStream(classF),classF.length());
       return cls;
}

/**
*
* @param name
* @param fileInputStream
* @param len
* @return
* @throws IOException
*/

private Class instantiateClass(String name,
FileInputStream fileInputStream, long len) throws IOException {
  byte[] raw = new byte[(int)len];
  fileInputStream.read(raw);
          fileInputStream.close();
return  defineClass(name,raw,0,raw.length);
}

protected Class loadClass(String name,boolean resolve)throws ClassNotFoundException{
Class cls = null;
cls = findLoadedClass(name);
if(!this.dynaclazz.contains(name) && cls == null)
cls = getSystemClassLoader().loadClass(name);
if(cls == null)
throw new ClassNotFoundException(name);
if(resolve)
resolveClass(cls);
return cls;

}
}

以上基本代码已经完成,如果有兴趣可以看看,写一个类来试试。看能不能替换。
如果真正能够明白,我想利用该机制能够很好的做好类的热运行。不在停止服务情况下,进行升级。
代码肯定不够好,希望各位好好拍。附件中有一个.pdf资料。想深入了解可以研究下。

参考的一些资料有:
http://en.wikipedia.org/wiki/Java_Classloader
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ClassLoader.html
分享到:
评论

相关推荐

    J2EE经典实例详解 <2>

    &lt;br&gt;&lt;br&gt;Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...

    J2EE经典实例详解 <4>

    &lt;br&gt;&lt;br&gt;Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...

    J2EE经典实例详解 <5>

    &lt;br&gt;&lt;br&gt;Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...

    J2EE经典实例详解 <3>

    &lt;br&gt;&lt;br&gt;Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...

    跟我学习注册表

    &lt;br&gt;&lt;br&gt;注册表基础知识 &lt;br&gt;注册表的由来 注册表的数据结构 &lt;br&gt;注册表的编辑 注册表的查找与修改 &lt;br&gt;注册表的内部结构 注册表的分析 &lt;br&gt; &lt;br&gt;注册表--根键详解 &lt;br&gt;HKEY_CLASSES_ROOT根键详解 &lt;br&gt;HKEY_USERS根...

    网管教程:从入门到精通(软件篇)

    &lt;br&gt;五:win2000/xp忘记密码的方法 &lt;br&gt;六:Windows XP 自带小工具 &lt;br&gt;七:windows中有关网络的几命令 &lt;br&gt;八:了解你的windows目录和系统文件 &lt;br&gt;九:低级格式化的主要作用 &lt;br&gt;十:封杀QQ消息连发器病毒 ...

    TCPIP协议详解(4-1)

    TCP/IP和Internet 8&lt;br&gt;2.1 一段历史 8&lt;br&gt;2.1.1 ARPANET 8&lt;br&gt;2.1.2 TCP/IP 9&lt;br&gt;2.1.3 国家科学基金会(NSF) 9&lt;br&gt;2.1.4 当今的Internet 12&lt;br&gt;2.2 RFC和标准化过程 12&lt;br&gt;2.2.1 获得RFC 13&lt;br&gt;2.2.2 RFC索引 13&lt;br...

    软件测试计划与测试用例设计

    目录&lt;br&gt;软件测试计划概述&lt;br&gt;测试计划的内容详解&lt;br&gt;测试用例概述&lt;br&gt;什么是测试用例&lt;br&gt;为什么需要测试用例&lt;br&gt;良好测试用例的特征&lt;br&gt;测试用例的组成元素与范例&lt;br&gt;白盒测试用例设计方法&lt;br&gt;等价类测试用例设计...

    电脑实用 快捷键大全

    转载于“就爱源码站” 第1节 word 快捷键 &lt;br&gt; 第2节 Excel 快捷键 &lt;br&gt; 第3...&lt;br&gt; 第15节 InDesignCS2 快捷键 &lt;br&gt; &lt;br&gt; 第16节 Editplus2快捷键 &lt;br&gt; 第17节 PageMaker 快捷键 &lt;br&gt; 第18节 文件扩展名详解 &lt;br&gt; &lt;br&gt;

    3D_java

    J2ME 3D手机游戏开发详解 源代码&lt;br&gt;-----------------------------光盘程序代码(源代码目录下)说明---------------------------------------&lt;br&gt;第2章&lt;br&gt;Hello3D 最基础的MIDlet例子,用于测试开发环境&lt;br&gt;第3章...

    TCP-IP技术大全

    TCP/IP和Internet 8&lt;br&gt;2.1 一段历史 8&lt;br&gt;2.1.1 ARPANET 8&lt;br&gt;2.1.2 TCP/IP 9&lt;br&gt;2.1.3 国家科学基金会(NSF) 9&lt;br&gt;2.1.4 当今的Internet 12&lt;br&gt;2.2 RFC和标准化过程 12&lt;br&gt;2.2.1 获得RFC 13&lt;br&gt;2.2.2 RFC索引 13&lt;br...

    vivi命令详解

    本文件为vivi的命令详解&lt;br&gt;13.6G嵌入式LINUX 视频教程免费下载&lt;br&gt;&lt;br&gt;http://www.verycd.com/topics/250252/&lt;br&gt;&lt;br&gt;以上为该视频教程的下载地址,希望对想学嵌入式的朋友能有用&lt;br&gt;&lt;br&gt;顺便借这个机会也做下广告...

    Delphi7 编程 100 实例

    ToolBar工具栏控件的使用&lt;br&gt;动态建立主菜单选项&lt;br&gt;窗口界面的动态分隔...器界面&lt;br&gt;如何生成半圆形窗口&lt;br&gt;制作字幕滚动窗体&lt;br&gt;详解Canvas生成渐变色窗口背景&lt;br&gt;WINAPM风格磁化窗口&lt;br&gt;软件封面的图片显示制作&lt;br&gt;...

    NS By Example

    目录:&lt;br&gt;Overview ,&lt;br&gt;Basics ,&lt;br&gt;OTcl: The User Language &lt;br&gt;Simple Simulation Example &lt;br&gt;Event Scheduler &lt;br&gt;Network Components &lt;br&gt;Packet &lt;br&gt;Post Simulation ,&lt;br&gt;Trace Analysis Example &lt;br&gt;...

    硬件工程师手册(全)

    硬件开发规范化管理 5&lt;br&gt;第一节 硬件开发流程 5&lt;br&gt;§3.1.1 硬件开发流程文件介绍 5&lt;br&gt;§3.2.2 硬件开发流程详解 6&lt;br&gt;第二节 硬件开发文档规范 9&lt;br&gt;§2.2.1 硬件开发文档规范文件介绍 9&lt;br&gt;§2.2.2 硬件开发文档...

    开放源码的计算机图形学几何算法包

    计算机图形学几何算法源码包,如下:&lt;br&gt;&lt;br&gt; 目录 &lt;br&gt;&lt;br&gt;㈠ 点的基本运算 &lt;br&gt;1. 平面上两点之间距离 1 &lt;br&gt;2. 判断两点是否重合 1 &lt;br&gt;3. 矢量叉乘 1 &lt;br&gt;4. 矢量点乘 2 &lt;br&gt;5. 判断点是否在线段上 2 &lt;br&gt;6. 求...

    C-C++语言趣味程序设计编程百例精解

    C/C++语言经典实用趣味程序设计编程百例精解(1) &lt;br&gt;(详解收藏在)http://www.klfd.net.cn/?p=384 &lt;br&gt;1.绘制余弦曲线 &lt;br&gt;2.绘制余弦曲线和直线 &lt;br&gt;3.绘制圆 &lt;br&gt;4.歌星大奖赛 &lt;br&gt;5.求最大数 &lt;br&gt;6.高次方数的尾数...

    java文集

    &lt;br&gt;DFS文件读写&lt;br&gt;网络爬虫之Spider&lt;br&gt;Java正则表达式的总结关键词: Java正则表达式 &lt;br&gt;批量上传--采集 (多个文件夹)&lt;br&gt;The Agile Way&lt;br&gt;hibernate mapping文件中的标记详解:关系标记&lt;br&gt;ANT 安装使用及...

Global site tag (gtag.js) - Google Analytics