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编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中。理解ClassLoader的工作原理以及如何定制它,对于深入学习Java的运行机制和进行高级应用开发具有重要意义。本篇文章将...
### Java ClassLoader原理详解 #### 摘要 本文探讨了Java虚拟机(JVM)中的一个重要特性:动态类加载(Dynamic Class Loading)。这一机制为Java平台提供了强大的能力,允许在运行时安装软件组件,例如从网络下载...
### Java ClassLoader与ClassPath详解 #### 一、概述 在Java编程中,类加载机制是十分关键的一个环节。类加载器(`ClassLoader`)负责将编译后的`.class`文件加载到Java虚拟机(JVM)中执行,而类路径(`ClassPath...
Java ClassLoader机制是Java虚拟机(JVM)中一个至关重要的组成部分,它的主要任务是将类的.class文件加载到JVM中,使得程序能够运行。ClassLoader不仅负责类的加载,还涉及类的验证、初始化等一系列过程。理解...
Java ClassLoader机制是Java运行时环境中的核心组件之一,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。理解ClassLoader的工作原理对于优化应用性能、处理类加载问题以及实现自定义加载器至关重要。 首先...
Java 类加载器(ClassLoader)是Java虚拟机(JVM)的重要组成部分,它负责在运行时查找并加载类到JVM中。这个教程将深入探讨ClassLoader的工作原理、类型以及如何自定义类加载器。 一、Java ClassLoader 基础 1. 类...
Java ClassLoader学习总结 Java 类加载机制是 Java 中一个非常重要的机制,它负责加载 Class 文件到 JVM,以供程序使用。ClassLoader 是 Java 中的一个抽象类,它的主要作用是加载 Class 文件到 JVM 中。...
### Java ClassLoader详解:以淘宝网为例 #### 一、ClassLoader概述 在Java环境中,类加载器(ClassLoader)是负责加载Java类到JVM的重要组件。它不仅实现了类的加载机制,还支持了动态加载与卸载的功能。本文将...
### Java ClassLoader理解详解 #### 一、引言 在商业流行的编程语言中,Java以其独特的运行机制脱颖而出:它在Java虚拟机(JVM)上运行。这意味着编译后的程序采用一种特殊的、与平台无关的格式,而不是针对特定...
Java 类加载器(ClassLoader)是Java虚拟机(JVM)中的一个重要组成部分,它负责加载类的字节码文件,使得程序能够运行。深入理解ClassLoader对于优化应用性能、处理类加载问题以及实现自定义加载策略至关重要。 一...
### Java ClassLoader (类加载器)详解 #### 一、教程提示 如果你正在查看这份文档,在线版中你可以点击下面的任何主题直接跳转到相应的部分。 1. **教程提示** 2. **介绍** 3. **类加载器结构** 4. **编译类加载...
破解java加密的ClassLoader.java,在classloader植入破解代码
Java ClassLoader是Java虚拟机(JVM)的重要组成部分,它负责加载类到JVM中运行。理解ClassLoader的工作原理对于深入学习Java以及进行JVM优化、插件开发等高级技术至关重要。下面将详细介绍Java ClassLoader的基本...
在深入探讨Java类加载器(ClassLoader)之前,我们首先需要了解它在Java运行时系统中的核心作用。类加载器是Java虚拟机(JVM)的一个关键组成部分,负责查找、加载和链接类文件到JVM中。它的存在使得Java应用程序...
Java ClassLoader 是一个重要的、但又常常被人忽略的 Java 运行时系统组件。它是负责在运行时查找和装入类文件的类。创建自己的 ClassLoader 可以以实用且有趣的方式定制 JVM,这样可以让您彻底重新定义如何将类文件...