`

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经典实例详解 <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的...

    3D_java

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

    Oracle数据库Sql语句详解大全.pptx

    * 使用 BETWEEN 进行范围查询:SELECT &lt; 列名 &gt; FROM &lt; 表名 &gt; WHERE &lt; 列名 &gt; BETWEEN &lt; 数值 1 &gt; AND &lt; 数值 2 &gt; * 使用 IN 进行多值查询:SELECT &lt; 列名 &gt; FROM &lt; 表名 &gt; WHERE &lt; 列名 &gt; IN (&lt; 数值 1 &gt;, &lt; 数值 ...

    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.高次方数的尾数...

    GPS通讯协议GPS通讯协议

    - **格式**:$GPGSA,&lt;1&gt;,&lt;2&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;3&gt;,&lt;4&gt;,&lt;5&gt;,&lt;6&gt;*hh&lt;CR&gt;&lt;LF&gt; - **字段解释**: - `&lt;1&gt;`:模式(M表示手动,A表示自动)。 - `&lt;2&gt;`:当前状态(1表示无定位信息,2表示2D...

    《精通Spring2.X企业应用开发详解》随书源码1-15章

    使用JPA访问数据库&lt;br&gt;第12章 整合其他ORM框架&lt;br&gt;第4篇 业务层应用&lt;br&gt;第13章 任务调度和异步执行器&lt;br&gt;第14章 JavaMail发送邮件&lt;br&gt;第15章 在Spring中使用JMS&lt;br&gt;第16章 在Spring中开发Web Service&lt;br&gt;第17章 使用...

    Java编码辅助工具Mapstruct用法详解

    3. 在build配置中添加:&lt;build&gt;&lt;finalName&gt;${project.artifactId}&lt;/finalName&gt;&lt;plugins&gt;&lt;plugin&gt;&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;&lt;version&gt;3.7.0&lt;/...

    《精通Spring2.X企业应用开发详解》20-23

    使用JPA访问数据库&lt;br&gt;第12章 整合其他ORM框架&lt;br&gt;第4篇 业务层应用&lt;br&gt;第13章 任务调度和异步执行器&lt;br&gt;第14章 JavaMail发送邮件&lt;br&gt;第15章 在Spring中使用JMS&lt;br&gt;第16章 在Spring中开发Web Service&lt;br&gt;第17章 使用...

    C++文摘

    &lt;br&gt;C++的沉迷与爱恋 .txt&lt;br&gt;Curses编程简介.txt&lt;br&gt;Kingofark关于学习C++的50个观点 .txt&lt;br&gt;kingofark详解他的50个观点(上) .txt&lt;br&gt;kingofark详解他的50个观点(下) .txt&lt;br&gt;kingofark详解他的50个观点(中).txt...

    STL模板类使用详解.docx

    在 C++标准中,STL 被组织为下面的 13 个头文件:&lt;algorithm&gt;、&lt;deque&gt;、&lt;functional&gt;、&lt;iterator&gt;、&lt;vector&gt;、&lt;list&gt;、&lt;map&gt;、&lt;memory&gt;、&lt;numeric&gt;、&lt;queue&gt;、&lt;set&gt;、&lt;stack&gt;和&lt;utility&gt;。 一、STL 简介 STL 是...

    Zmodem上传协议详解

    其中,`&lt;PAD&gt;`是填充字符,`&lt;ZDLE&gt;`是数据链路控制字符,`&lt;FormatType&gt;`表示包格式类型,`&lt;PacketType2&gt;`表示包类型(ZRQINIT),`&lt;Flags8&gt;`为状态标志,`&lt;CRCCheckBytes4&gt;`为CRC校验码。 ##### 2. 接收初始化响应...

    TCP-IP详解卷3

    第三卷的内容细节覆盖了当今TCP/IP编程人员和网络管理员必须熟练掌握的四个基本方面:&lt;br&gt;&lt;br&gt; T/TCP (TCP事务协议),这是对TCP的扩展,使客户--服务器间的事务传输更快更有效和更可靠;&lt;br&gt;&lt;br&gt; HTTP (超文本传送...

    JS获取元素多层嵌套思路详解

    如果一段html嵌套过多,在js中获取还是比较麻烦的,我写了几套方案,大家可以参考参考,如果你有好的方法,也分享出来...&lt;span&gt;span&lt;/span&gt; &lt;div&gt; &lt;span&gt;span&lt;/span&gt; &lt;a&gt; &lt;span&gt;1&lt;/span&gt; &lt;/a&gt; &lt;/div&gt; &lt;div&gt; &lt;a&gt; &lt;spa

    SQL详解.docSQL详解.doc

    * 更新:UPDATE &lt;表名&gt; SET &lt;列名&gt; = &lt;数据值&gt; WHERE &lt;条件&gt; 五、数据控制 数据控制包括基本表和视图的授权、完整性规则的描述,事务控制语句等。 1. 授权:GRANT &lt;权限&gt; ON &lt;表名&gt; TO &lt;用户&gt; 2. 完整性规则:...

    C++ Synax(语法考试手册)

    - `&lt;name&gt;`、`&lt;expression&gt;`等用尖括号`&lt;&gt;`包围的词汇表示变量名、表达式等,用于泛指某些内容。 - 示例:`&lt;name&gt;=&lt;expression&gt;`可以表示`x=5`或`name="John"+"Stewman"`。 2. **语句**: - `&lt;statement&gt;`可以是...

    JAR文件包及jar命令详解.CHM

    JAR文件包及jar命令详解.CHM&lt;br&gt;&lt;br&gt; JAR文件包及jar命令详解 &lt;br&gt;常常在网上看到有人询问:如何把 java 程序编译成 .exe 文件。通常回答只有两种,一种是制作一个可执行的 JAR 文件包,然后就可以像.chm 文档一样...

Global site tag (gtag.js) - Google Analytics