`
五月天
  • 浏览: 21210 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java类加载器加载机制

阅读更多

类加载器(class loader)用来加载 Java 字节码到 java虚拟机中,即类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。

在java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器:

BookStrap,  ExtClassLoader,  AppClassLoader

类加载器也是java类,所以java类加载器本身也要被其它类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap.

 

 

java虚拟机中所有的类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定父级类加载器

 

类加载器之间的父子关系和管辖范围

 

可以通过下面的测试程序验证类加载器的委托机制:

public class ClassLoderTest1 {

	public static void main(String[] args) {
		
		ClassLoader loder = ClassLoderTest1.class.getClassLoader();
		while (loder != null) {
			System.out.println(loder.getClass().getName());
			loder = loder.getParent();
		}
	}
}
/*
 * sun.misc.Launcher$AppClassLoader
 * sun.misc.Launcher$ExtClassLoader
 */ 
从结果可以看出,首先AppClassLoader会加载ClassLoderTest1.class,由于委派机制会先使用其父加载器ExtClassLoader去加载,这就是为什么打印出上面的结果。

 

 

下面介绍下ClassLoader

java.lang.ClassLoader 类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类,即 java.lang.Class 类的一个实例。除此之外,ClassLoader 还负责加载 Java 应用所需的资源,如图像文件和配置文件等

ClassLoader 中与加载类相关的方法

 

方法

说明

getParent()

返回该类加载器的父类加载器。

loadClass(String name)

加载名称为 name 的类,返回的结果是 java.lang.Class 类的实例。

 

findClass(String name)

查找名称为 name 的类,返回的结果是 java.lang.Class 类的实例。

 

findLoadedClass(String name)

查找名称为 name 的已经被加载过的类,返回的结果是 java.lang.Class 类的实例。

 

defineClass(String name, byte[] b, int off, int len)

把字节数组 b 中的内容转换成 Java 类,返回的结果是 java.lang.Class 类的实例。这个方法被声明为 final 的。

 

resolveClass(Class<?> c)

链接指定的 Java 类。

 

当我们自定义类加载器时会用到上面的方法。

下面我们来自定义加载器实现加载特定目录下面的.class文件。

这里我们来加载lib目录下面的字节码文件。

首先我们来定义一个目标文件

public class ClassLoaderDemo extends Date {

	public String toString() {
		return "这是被类加载器加载的哦";
	}	
}

 

让其实现Date类是便于后面的测试

 

然后我们开始编写自定义的类加载器了

public class CustomClassLoader extends ClassLoader {

	/**
	 * 复写findClass()方法
	 */
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		
		byte[] data = getClassData(name);
		if (data == null) {
			throw new ClassNotFoundException();
		}
		//通过byte[]数组得到Class
		return defineClass(null, data, 0, data.length);
	}

	/**
	 * 从lib目录中得到字节码文件,并转成byte[]数组
	 * @param name
	 * @return
	 */
	private byte[] getClassData(String name) {
		
		String classSrc = "lib" + File.separator + getClassName(name) + ".class";
		try {
			FileInputStream in = new FileInputStream(classSrc);
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024*4]; 
			int len = 0;
			while ((len = in.read(buffer)) != -1) {
				out.write(buffer, 0, len);
			}
			return out.toByteArray();
		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 
	 * @param classNamePath 形如:cn/zcl/lib/ClassLoaderDemo.class
	 * @return ClassLoaderDemo.class
	 */
	private String getClassName(String classNamePath) {
		
		return classNamePath.substring(classNamePath.lastIndexOf(".") + 1);
	}
	
}

 

其实实现类加载器只需继承ClassLoader,并覆写里面的findClass()方法。

 

最后测试一个测试类来测试我们写的类加载器是否成功

public class ClassLoaderTest2 {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

		Date date = (Date)new CustomClassLoader().loadClass("cn.zcl.classLoaderDemo").newInstance();
		System.out.println(date);
	}
}

 

打印结果:

这是被类加载器加载的哦 
这就表明我们写得自定义加载器已经成功。

 

下面总结下:

编写自定义的类加载器只需继承ClassLoader,并覆写里面的findClass()方法,将字节码文件转成Class实例,当然这里面使用到了defineClass()将字节数组转成Class实例。

扩展:

当在做开发中,出现类转换异常时,除了一般的转换外,还得注意是否一个类被两个类加载器加载,若一个类被两个类加载器加载,这两个字节码在内存中是不相等的,这点非常关键。 

分享到:
评论

相关推荐

    java类加载器实例

    类加载器是 Java 语言的一个创新,也是 ...不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试 ClassNotFoundException和 NoClassDefFoundError等异常。

    Java类加载机制与反射-PPT

    Java的类加载机制:加载,连接,初始化。JAVA类加载器: Bootstrap ClassLoader : 根类加载器, Extension ClassLoader: 扩展类加载器, System ClassLoader : 系统类加载器, Java反射

    java类加载机制.xmind

    该文件是JVM中关于类加载机制的知识整理的思维导图,包括类加载机制概述、类加载的生命周期、加载时机、加载过程、类加载、类的初始化和实例化等几个大方面进行了讲解,其中类加载中还对JVM三种预定义类加载器进行了...

    自定义Java类加载器demo

    自定义Java类加载器demo,自定义了一个classLoader,重写了loadClass 和findClass,注意 loadClass打破了双亲委派机制,所有的类都要在自定义的class文件中找到,而findClass遵循了双亲委派机制

    Java类加载器机制与模型.pdf

    Java类加载器机制与模型

    java类加载器和反射学习要点ppt

    本学习讲义是关于java类加载和反射机制需要注意的要点学习,内容详细

    ClassLoader类加载机制

    类加载器是 Java 语言的一个创新,也是 ...不过如果遇到了需要与类加载器进行交互的情况,而对类加载器的机制又不是很了解的话,就很容易花大量的时间去调试 ClassNotFoundException和 NoClassDefFoundError等异常。

    java类加载器和核心机制.pdf

    java类加载器和核心机制.pdf

    深入理解java类加载机制

    此外,我们还会探讨Java程序的类加载器和双亲委派机制,以及自定义类加载器和类卸载的实现原理和应用方法。 总的来说,本资源将为Java程序员提供全面的Java字节码和类加载原理和实践经验。通过学习本资源,开发人员将...

    Java类加载机制.doc

    对java的类加载机制,进行了深入的解析,并详细的实现了客户化加载器。

    JAVA ClassLoader 讲解 (类加载器)

    ClassLoader类加载器讲解,理解JAVA类加载机制

    java 类加载器学习笔记1

    /** * java类加载器 * 类加载器负责加载与连接,这个过程是在运行时进行的,这种机制为java提供极大的灵活性 * * 类的生命周期 * class文件

    java的ClassLoader类加载器机制

    jvm运行的过程中,需要载入类,而类的加载需要类加载器,本文章提供了java的类加载器的工作原理。可以使读者更加理解jvm的运行机制。

    Java类加载机制学习1

    (1)双亲模型类加载器的作用:从class文件定义出class对象通过defineClass()方法进行定义类加载器 初始类加载器关系:该类的定义类加载器是该类

    Java类加载器和类加载机制实例分析

    主要介绍了Java类加载器和类加载机制,结合实例形式分析了java类加载器与类加载机制原理、实现方法及相关操作技巧,需要的朋友可以参考下

    Java基础加强之类加载器

    学习概述:本模块深入讲解了Java类加载方面的知识,Java类加载器和类加载机制以及类加载原理  学习目标:掌握类加载机制和原理,能够独立开发自己的类加载器。  1.类的加载  什么是类加载? 类加载是指将类的...

    java 类加载调试

    他们提供的见解有助亍理解和解决常见的 Java 异常,例如 NoClassDefFoundError 和 ClassNotFoundException,以及更有挅戓性的问题,例如类装入器约束迗反和死锁。在第 1 部分中,他们详细描述了 Java 类装入的工作...

    全面解析Java类加载器

    深入理解和探究Java类加载机制—-  1.java.lang.ClassLoader类介绍  java.lang.ClassLoader类的基本职责是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java 类,即 ...

    详解JAVA类加载机制(推荐)

    JAVA源码编译由三个过程组成: 1、源码编译机制。 2、类加载机制 ...系统可能在第一次使用某个类时加载该类,也可能采用预加载机制来加载某个类,当运行某个java程序时,会启动一个java虚拟机进程,两次运行

    Java 类加载机制详解

     二、类的加载机制  在Java中,采用双亲委派机制来实现类的加载。那什么是双亲委派机制?在Java Doc中有这样一段描述:  The ClassLoader class uses a delegation model to search for classes and resources

Global site tag (gtag.js) - Google Analytics