- 浏览: 153143 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (130)
- Database (5)
- JavaSE (23)
- JavaScript (11)
- Struts2 (15)
- Hibernate (11)
- Spring (16)
- Linux (4)
- Jquery (3)
- Tools (12)
- Jsp (7)
- 杂谈 (9)
- WEB Project (10)
- WebService (16)
- maven (2)
- android (1)
- memcache (2)
- 网络通信 (4)
- solr (1)
- cxf (7)
- powerdesigner (1)
- jxls (1)
- springmvc (1)
- nosql (1)
- node.js (0)
- thrift (0)
- REST (1)
- tag (1)
最新评论
由于一个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
下面是我对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
发表评论
-
Java编程中“为了性能”尽量要做到的一些地方
2012-07-04 14:44 6221.慎用synchronized,尽量减小synchroniz ... -
利用Session防止表单重复提交
2011-12-13 18:36 11461 由于服务器缓慢或者 ... -
java format(MessageFormat)
2011-12-06 17:20 738java.text.Format |__java. ... -
java 主线程等待子线程执行完成后再执行
2011-12-06 09:47 3151原文:http://www.jiacheo.org/blog ... -
Ognl/MVEL/Aviator/JSEL 四种表达式引擎执行效率对比
2011-11-24 10:33 2935http://jindw.iteye.com/blog/732 ... -
java模拟javascript的encodeURI方法
2011-10-27 15:52 2891import java.io.UnsupportedEncod ... -
3种下载文件程序的思考,为何使用NIO进行异步网络通讯
2011-10-08 14:37 653原文链接:http://suhuanzheng7784877 ... -
cglib 动态代理
2011-08-12 10:35 711cglib is a powerful, high perfo ... -
【温故而知新】log4j输出多个自定义日志文件,动态配置路径
2011-08-10 15:38 8361. log4j输出多个自定义日志文件 log ... -
java7 新特性
2011-08-10 10:48 691原文链接:http://www.iteye ... -
Java版短网址(ShortUrl)的算法
2011-06-09 10:42 2725最近,我的项目中需要用到短网址(ShortUrl)的算法,于是 ... -
设计模式学习——适配器模式
2011-06-07 10:30 726某个类拥有我们所 ... -
用spring做一个javaMail功能的例子
2011-05-16 09:37 1191前言:项目中要做一个发送邮件的功能,在网上搜了一些代码,说的都 ... -
UML中几种类间关系:继承、实现、依赖、关联、聚合、组合的联系与区别
2010-10-14 18:38 835今天看到一篇好文,觉得还不错,褪去的记忆被唤醒:http:/ ... -
动态代理
2010-07-13 11:11 704http://www.iteye.com/topic/7103 ... -
ASCLL,Unicode 和 UTF-8
2010-05-15 13:36 14371.Ascll 算是比较早的编码,七位二进制数表示,当然在 ... -
String 详解
2010-05-12 10:29 762解析Java中的String对象的数据类型 1. 首先S ... -
判断数据的类型
2010-05-04 15:24 791// 字符类型 String if (pramets.get( ... -
关于ThreadLocal模式的体会
2010-03-18 11:00 1176本文转至::http://www.iteye.com/topi ... -
properties 文件 读写
2010-03-10 10:18 897import java.io.BufferedInputStr ...
相关推荐
<br><br>Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...
<br><br>Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...
<br><br>Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...
<br><br>Java技术采用了两个象征性的符号,一个是一杯冒着热气的咖啡,一个是Duke这个有趣的卡通人物。Duke在线银行实例是美国Sun Microsystems公司在其《J2EE学习指南》中使用的一个完整实例,该实例涵盖了Java的...
<br><br>注册表基础知识 <br>注册表的由来 注册表的数据结构 <br>注册表的编辑 注册表的查找与修改 <br>注册表的内部结构 注册表的分析 <br> <br>注册表--根键详解 <br>HKEY_CLASSES_ROOT根键详解 <br>HKEY_USERS根...
<br>五:win2000/xp忘记密码的方法 <br>六:Windows XP 自带小工具 <br>七:windows中有关网络的几命令 <br>八:了解你的windows目录和系统文件 <br>九:低级格式化的主要作用 <br>十:封杀QQ消息连发器病毒 ...
TCP/IP和Internet 8<br>2.1 一段历史 8<br>2.1.1 ARPANET 8<br>2.1.2 TCP/IP 9<br>2.1.3 国家科学基金会(NSF) 9<br>2.1.4 当今的Internet 12<br>2.2 RFC和标准化过程 12<br>2.2.1 获得RFC 13<br>2.2.2 RFC索引 13<br...
目录<br>软件测试计划概述<br>测试计划的内容详解<br>测试用例概述<br>什么是测试用例<br>为什么需要测试用例<br>良好测试用例的特征<br>测试用例的组成元素与范例<br>白盒测试用例设计方法<br>等价类测试用例设计...
转载于“就爱源码站” 第1节 word 快捷键 <br> 第2节 Excel 快捷键 <br> 第3...<br> 第15节 InDesignCS2 快捷键 <br> <br> 第16节 Editplus2快捷键 <br> 第17节 PageMaker 快捷键 <br> 第18节 文件扩展名详解 <br> <br>
J2ME 3D手机游戏开发详解 源代码<br>-----------------------------光盘程序代码(源代码目录下)说明---------------------------------------<br>第2章<br>Hello3D 最基础的MIDlet例子,用于测试开发环境<br>第3章...
TCP/IP和Internet 8<br>2.1 一段历史 8<br>2.1.1 ARPANET 8<br>2.1.2 TCP/IP 9<br>2.1.3 国家科学基金会(NSF) 9<br>2.1.4 当今的Internet 12<br>2.2 RFC和标准化过程 12<br>2.2.1 获得RFC 13<br>2.2.2 RFC索引 13<br...
本文件为vivi的命令详解<br>13.6G嵌入式LINUX 视频教程免费下载<br><br>http://www.verycd.com/topics/250252/<br><br>以上为该视频教程的下载地址,希望对想学嵌入式的朋友能有用<br><br>顺便借这个机会也做下广告...
ToolBar工具栏控件的使用<br>动态建立主菜单选项<br>窗口界面的动态分隔...器界面<br>如何生成半圆形窗口<br>制作字幕滚动窗体<br>详解Canvas生成渐变色窗口背景<br>WINAPM风格磁化窗口<br>软件封面的图片显示制作<br>...
目录:<br>Overview ,<br>Basics ,<br>OTcl: The User Language <br>Simple Simulation Example <br>Event Scheduler <br>Network Components <br>Packet <br>Post Simulation ,<br>Trace Analysis Example <br>...
硬件开发规范化管理 5<br>第一节 硬件开发流程 5<br>§3.1.1 硬件开发流程文件介绍 5<br>§3.2.2 硬件开发流程详解 6<br>第二节 硬件开发文档规范 9<br>§2.2.1 硬件开发文档规范文件介绍 9<br>§2.2.2 硬件开发文档...
计算机图形学几何算法源码包,如下:<br><br> 目录 <br><br>㈠ 点的基本运算 <br>1. 平面上两点之间距离 1 <br>2. 判断两点是否重合 1 <br>3. 矢量叉乘 1 <br>4. 矢量点乘 2 <br>5. 判断点是否在线段上 2 <br>6. 求...
C/C++语言经典实用趣味程序设计编程百例精解(1) <br>(详解收藏在)http://www.klfd.net.cn/?p=384 <br>1.绘制余弦曲线 <br>2.绘制余弦曲线和直线 <br>3.绘制圆 <br>4.歌星大奖赛 <br>5.求最大数 <br>6.高次方数的尾数...
<br>DFS文件读写<br>网络爬虫之Spider<br>Java正则表达式的总结关键词: Java正则表达式 <br>批量上传--采集 (多个文件夹)<br>The Agile Way<br>hibernate mapping文件中的标记详解:关系标记<br>ANT 安装使用及...