<%@ page contentType="text/html; charset=gb2312"%> Java虚拟机(JVM)的动态类加载(Class Loading)
网站公告:   ◆北天JAVA技术网热情为java爱好者服务,本网内容包括JAVA(JSP、servlet、EJB、webservice、j2ee、javabean、应用服务器、JavaScript),数据库(MYSQL、SQL Server、Sybase、Oracle、DB2、数据库综合知识),设计研究(设计模式、Struts、Spring、Hibernate、设计框架、设计综合知识),WEB2.0新技术(主要介绍AJAX),以及各种技术的入门、实例、例子等等,欢迎各位多来坐坐!◆  诚邀各位JAVA爱好者加盟!◆  本网站内容丰富,更新快,保证每周20篇以上!  
加入收藏
设为首页
联系站长
承接项目
  相关资源:网站首页 | 免费培训学院 | 技术论坛 | JAVA聊天室 | 作家专栏 | 开发工具 | 认证考试 | 会员俱乐部
  JAVA技术初学者园地 | jsp与servlet | javascript | Java源代码 | EJB | web service | 应用服务器 | JAVA综合知识
  设计研究设计模式 | 设计框架 | Struts | Spring | Hibernate | 开源项目 | 面向对象设计 | 设计综合知识
  数 据 库MYSQL | SQL Server | Sybase | Oracle | DB2 | Informix | Access | 数据库综合知识
  其他资源:AJAX新技术 | 网站开发 | ERP软件 | OA办公软件 | 商业智能BI | 开发综合知识 | 承接项目 | 项目试用

 
 
Java虚拟机(JVM)的动态类加载(Class Loading)
     发布者: 发布时间:2007-09-23
1.介绍

Class Loaders是动态加载Java类与Resource的一种机制。它支持Laziness,type-safe linkage,user-defined extensibility和multiple communicating namespaces这4种特性。

l Lazy loading:Class只有在需要的时候才加载。这样减少了内存使用量,能提高系统反映速度;

l Type-safe linkage:动态类加载不会破坏JVM的类型安全;

l User-definable class loading policy:开发者可以自定义的类加载器,控制动态类加载过程;

l Multiple namespaces:JVM允许使用不同的类加载器加载相同的Class名称,但不同内容的类。

Class Loaders早在JDK1.0时就已存在,最开始的目的是使HotJava浏览器能加载Applet。从那以后,动态类加载机制被广泛应用到其他方面,例如web application server中Servlets的加载。class loader在JDK 1.0,1.1版本存在的缺陷,已经在JDK 1.2解决,其缺陷主要是编写不正确的Class Loader会造成类型安全问题。

2.Class Loaders

Class Loader的目的是动态加载Java类和Resource。Java类是平台无关的,标准的,具有规范二进制文件格式的。class文件有编译器生成,可以被任何一中JVM加载。Java类的表现形式不仅只有.class文件,还可以为内存buffer,或是网络数据流。

JVM执行class文件内的Byte code。但是Byte code不是class文件的全部内容,class文件内还包含符号表,表示类,属性和方法名,以及类内引用到其他类,属性,和方法名。例如下面的类

class C{

void f(){

D d=new D();

}

}

类文件内类C引用D。为了能让JVM知道D类是什么,JVM必须要先load D的class file并创建D class对象。

JVM使用类加载器加载类文件,并创建Class对象。类加载器都是ClassLoader的子类实例。ClassLoader.loadClass方法通过获得一个类名,返回一个Class对象,表示该类的类型。上面的代码里,假设C被类加载器L加载,则L是C的加载器。JVM将使用L加载所有被C引用到的其他Java类。

如果D还没有被加载,L将加载D:

L.loadClass(“D”)

当D已经被加载,JVM就可以创建D的一个对象实例。

一个Java应用程序可以使用不同类型的类加载器。例如Web Application Server中,Servlet的加载使用开发商自定义的类加载器, java.lang.String在使用JVM系统加载器,Bootstrap Class Loader,开发商定义的其他类则由AppClassLoader加载。在JVM里由类名和类加载器区别不同的Java类型。因此,JVM允许我们使用不同的加载器加载相同namespace的java类,而实际上这些相同namespace的java类可以是完全不同的类。这种机制可以保证JDK自带的java.lang.String是唯一的。

ClassLoader子类需要重载loadClass方法以实现用户自己的类加载方式,下面是自定义一个类加载器例子:

package org.colimas.webapp;



import java.io.File;

import java.io.IOException;

import java.net.URL;

import java.net.URLClassLoader;

import java.util.StringTokenizer;





/**

*类加载器加载Servlet,URLClassLoader是ClassLoader的一个子类,可以通过URL加载Java类或其它资源。

* @author 趙磊

*

*/

public class WebAppClassLoader extends URLClassLoader {



private ClassLoader _parent;



public WebAppClassLoader(ClassLoader parent) {

super(new URL[0], parent);

_parent=parent;

if (parent==null)

throw new IllegalArgumentException("no parent classloader!");

}

//追加一个Class Path。

public void addClassPath(String classPath) throws IOException{

if (classPath == null)

return;

StringTokenizer tokenizer= new StringTokenizer(classPath, ",;");

while (tokenizer.hasMoreTokens())

{

URL url=null;

File file=new File(tokenizer.nextToken()).getCanonicalFile();

url=file.toURI().toURL();

addURL(url);

}

}

//加载类

public synchronized Class loadClass(String name)

throws ClassNotFoundException {



return loadClass(name,false);

}



protected synchronized Class loadClass(String name, boolean resolve)

throws ClassNotFoundException {



Class c= findLoadedClass(name);



ClassNotFoundException ex= null;





if (c == null && _parent!=null ){



try{



c= _parent.loadClass(name);



}catch (ClassNotFoundException e){

ex= e;



}



}



if (c == null){



try{

c= this.findSystemClass(name);



}catch (ClassNotFoundException e){



ex= e;



}



}



if (c == null)



throw ex;







if (resolve)



resolveClass(c);



return c;

}

}

loadClass方法中使用findLoadedClass方法检查类是否已经被加载。该方法是Native方法,实现在JVM的ClassLoader.c文件内的Java_java_lang_ClassLoader_findLoadedClass函数。如果返回为null,则表示类还没有被加载,于是在其Parent类加载器重寻找_parent.loadClass,如果仍然返回null,则要在系统中查找,findSystemClass,如果仍然没有,则抛出异常。我们要确保多线程在同一时间只能加载一次,因此需要synchronized。

通常我们需要动态更新一个Class。例如一个Servlet实现发生变化时,我们希望不是重启服务器而是Reload。下面的类ServletWrapper提供了一个Servlet Reload的实现方法:

package org.colimas.webapp;



import javax.servlet.Servlet;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;



/**

* @author 趙磊

*

*/

public class ServletWrapper {



private Servlet theServlet;

private Class servletClass;

private ServletConfig config;

private String _servletname;



public ServletWrapper(ServletConfig config){

this.config=config;

}



public Servlet getServlet() throws ServletException{

synchronized (this) {



destroy();



try {



WebAppClassLoader loader=new WebAppClassLoader(this.getClass().getClassLoader());

String name=getServletName();

servletClass = loader.loadClass(name);



theServlet = (Servlet) servletClass.newInstance();





} catch( ClassNotFoundException ex1 ) {



} catch( InstantiationException ex ) {



}catch(IllegalAccessException ex2){



}



theServlet.init(config);

}

return theServlet;

}

public void destroy() {

if (theServlet != null) {

theServlet.destroy();

}

}



protected String getServletName(){

return _servletname;

}

}

getServlet()获得一个Servlet对象。首先创建一个新的Servlet类加载器。loader.loadClass加载最新的Servlet,servletClass.newInstance()实例化新的Servlet对象,并theServlet.init(config);让它运行起来。这种方法只有在不改变Servlet的接口时有效的。如果你要加载的类不实现任何接口,那么就不能在ServletWrapper直接使用该类名。而是定义为Object theServlet,并且theServlet = servletClass.newInstance();,而theServlet.init(config);也不得不改写为:

Method m= servletClass.getMethod(“init”,…);

m.invoke(theServlet,…);



3. Type-safe Linkage和Namespace一致性



JVM使用loaded class cache保存class名和加载该class的类加载器。当JVM通过loadClass获得class之后,它执行以下操作:

l 检查传给loadClass的类名是否和真实类名一致;

l 如果一致,则保存到loaded class cache里。

ClassLoader.findLoadedClass就是在loaded class cache查找class是否存在的。

为了保证Type-safe,Sun公司做了很多工作,目前也有不止一个解决方案。例如,增加约束规则(Contraint Rule)等。

(转载文章请保留出处:北天JAVA技术网(www.java114.com))
 
更多精彩文章:
JAVA 7新特性让JVM“瘦身”成功!
用JPDA轻松调试Java代码
Java技巧:用匿名类来实现简化程序调试
Java技巧:用匿名类来实现简化程序调试
对Java语言中的日期处理大全
简单介绍JSP数据库高级操作
 
最近评论:
        
鍥炲
        
那个雨天的想法!
wow gold,wow power leveling.wow power leveling,wow power leveling, max(9692)
        
如果真的有来生!
四川旅游,九寨沟旅游,稻城亚丁旅游,四姑娘山旅游,海螺沟旅游,西藏旅游, max(4795)
        
那天的情景!
Maple Story mesos,MapleStory mesos,ms mesos,mesos,SilkRoad Gold, max(9240)
        
轻轻走过你的窗前!
world of warcraft gold,cheap world of warcraft gold,warcraft gold,world of warcraft gold,cheap world of warcraft gold,warcraft gold max(7376)
        
不在的哪天!
final fantasy xi gil,final fantasy xi gil,final fantasy xi gil,final fantasy xi gil, max(1815)
        
快乐情人节!
wow gold,wow gold,wow gold,wow gold,wow gold,wow gold,wow gold buy wow gold for cheap. max(8143)
        
昨夜的狂想曲!
wow gold,WoW Gold,world of warcraft gold,WoW Gold, max(3103)
        
没有情人的情人节!
wow gold,wow power leveling.wow power leveling,wow power leveling, max(3272)
        
远方的你!
world of warcraft gold,wow gold,a href="http://www.gogoer.com">world of warcraft gold,cheap world of warcraft gold max(5406)
        
标 题:   
内 容:   
 
                                  
 
免责声明:该文章由网友发表,如果对您造成侵权,请联系站长

首页 - 承接项目 - 网站地图 - 联系我们 -
版权所有北天JAVA技术工作室 ICP证号:粤ICP备06079815号