`
czjxdm
  • 浏览: 123725 次
社区版块
存档分类
最新评论

Java虚拟机(JVM)的动态类加载(转)

阅读更多
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虚拟机JVM类加载初始化

    Java虚拟机JVM类加载初始化是Java程序运行过程中的关键环节,它负责将类的字节码文件加载到内存中并进行相应的处理,以便程序能够正确执行。在Java中,类加载器(Classloader)扮演着核心角色。下面将详细讨论类加载...

    深入Java虚拟机JVM类加载学习笔记

    ### 深入Java虚拟机JVM类加载学习笔记 #### 一、Classloader机制解析 在Java虚拟机(JVM)中,类加载器(ClassLoader)是负责将类的`.class`文件加载到内存中的重要组件。理解类加载器的工作原理对于深入掌握JVM以及...

    深入理解Java虚拟机JVM高级特性与最佳实践1

    《深入理解Java虚拟机JVM高级特性与最佳实践》是一本专注于Java开发人员提升技术水平的著作,由周志明撰写。这本书旨在填补Java技术体系中关于Java虚拟机(JVM)知识的空白,帮助读者深入理解JVM的工作原理及其对...

    Java虚拟机JVM类加载学习笔记

    Java虚拟机(JVM)是Java程序的核心组成部分,它负责执行字节码并管理程序运行时的内存。本文主要探讨JVM的类加载机制,包括类加载、连接、初始化等关键过程,以及类的主动使用和被动使用的情况。 首先,我们要理解...

    实战JAVA虚拟机 JVM故障诊断与性能优化.rar

    《实战JAVA虚拟机 JVM故障诊断与性能优化》是一本深度探讨Java虚拟机(JVM)的专著,旨在帮助开发者解决实际工作中遇到的JVM相关问题,提升系统的性能表现。通过对JVM内部机制的深入理解,我们可以更有效地调试、...

    实战JAVA虚拟机 JVM故障诊断与性能优化

    《实战JAVA虚拟机—JVM故障诊断与性能优化》是一本深入探讨Java虚拟机(JVM)技术的书籍,旨在帮助开发者和系统管理员诊断并优化JVM相关的性能问题。本书内容丰富,涵盖了大量的实践案例,使得即便是初学者也能理解...

    揭秘Java虚拟机-JVM设计原理与实现

    《揭秘Java虚拟机-JVM设计原理与实现》这本书深入探讨了Java虚拟机(JVM)的工作原理及其在Java编程中的核心地位。Java虚拟机是Java平台的核心组成部分,它负责执行字节码,为开发者提供了跨平台的运行环境。以下是...

    实战Java虚拟机 JVM故障诊断与性能优化 葛一鸣

    《实战Java虚拟机 JVM故障诊断与性能优化》是由葛一鸣编著的一本专业书籍,主要探讨了如何在实际工作中解决Java虚拟机(JVM)的相关问题,以及如何进行性能调优。书中涵盖了许多关键的知识点,让我们一一展开讨论。 ...

    深入Java虚拟机 JVM pdf

    《深入Java虚拟机》是Java开发者必读的经典之作,它详细阐述了Java虚拟机(JVM)的工作原理和内部机制,对于理解Java程序的运行方式、优化代码性能以及排查问题具有极其重要的价值。这本书的第二版更是加入了更多...

    深入Java虚拟机_002_深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器

    Java虚拟机(JVM)是Java程序运行的核心,它负责解释和执行字节码,使得Java具有跨平台的能力。在Java编程中,类加载器(Class Loader)扮演着至关重要的角色,它负责查找并加载Java类到JVM内存中。本部分我们将深入...

    Java虚拟机类加载顺序

    在Java开发中,了解类是如何被加载到Java虚拟机(JVM)中的至关重要。本文将详细介绍JVM中的类加载顺序及其背后的原理,帮助读者理解这一过程,并掌握如何利用类加载机制解决实际问题。 #### 二、类加载器层次结构 ...

    JAVA虚拟机(JVM)规范(中文版).rar

    **JAVA虚拟机(JVM)规范** JAVA虚拟机(JVM)是Java语言的核心组成部分,它为Java程序提供了运行环境,使得Java代码能在任何支持JVM的平台上运行,实现了“一次编写,到处运行”的目标。JVM规范定义了Java程序如何...

    使用C++创建java虚拟机JVM,使用JNI调用java函数.zip

    在提供的资源"使用C++创建java虚拟机JVM,使用JNI调用java函数"中,可能详细介绍了以上步骤的实际应用,包括代码示例和可能遇到的问题及解决方案。通过学习和实践这个教程,开发者可以更好地理解和掌握C++与Java之间...

    Java 虚拟机JVM内存模型

    ### Java 虚拟机JVM内存模型知识点 #### 1. JVM概述 ##### 1.1 Java的特性与JVM的应用 Java语言的特性包括跨平台性、面向对象、安全性等。JVM是Java程序能够跨平台运行的关键,它负责将Java源代码转换成与平台无关...

    Java虚拟机JVM面试题目

    "Java虚拟机JVM面试题目" Java虚拟机(JVM)是Java程序的运行环境,它负责编译、加载、执行Java字节码,并提供了垃圾回收、内存管理、安全机制等功能。下面是JVM面试题目相关的知识点: 一、JVM架构 JVM包含两个...

    深入理解Java虚拟机(jvm性能调优+内存模型+虚拟机原理).zip

    《深入理解Java虚拟机》是一本深度探讨Java虚拟机(JVM)的著作,涵盖了JVM性能调优、内存模型以及虚拟机原理等多个关键领域。本文将基于这些主题,详细阐述其中的重要知识点。 首先,我们要了解Java虚拟机(JVM)...

    浅谈JAVA虚拟机JVM及工作原理

    "浅谈JAVA虚拟机JVM及工作原理" Java虚拟机(JVM)是Java语言的 runtime 环境,它提供了一个平台独立的环境,使得Java程序可以跨平台运行。JVM 的主要组件包括虚拟机栈、堆、方法区、程序计数器、本地方法栈等。 1...

    java虚拟机

    Java虚拟机(JVM,Java Virtual Machine)是Java平台的核心组成部分,它负责执行Java程序,为Java代码提供了跨平台的运行环境。Java虚拟机的概念始于Sun Microsystems,现在由Oracle公司继续发展和维护。JVM的设计...

Global site tag (gtag.js) - Google Analytics