Java重要技术(29)类加载器之类加载器的职责

1.1. 类加载器的职责

每个类(Class)都有一个类加载器。类加载器ClassLoader的职责包括以下内容:

(1)类的定位。根据类的名称找到对应的class文件,也可以不需要class文件。

(2)类的定义。产生表达类的定义的Class类的实例。

某个Sample类的代码如下:

package com.test.javatechnology.classloader.test;

//Sample类的class文件将位于test目录下。

public class Sample {

//NOTHING.

}

定制的MyClassLoader的代码如下:

/**   

* @Title: MyClassLoader.java

* @Package com.test.javatechnology.classloader

* @Description:

* @author http://www.cnblogs.com/coe2coe/

* @date 2017年4月4日 下午9:52:47

* @version V1.0   

*/

package com.test.javatechnology.classloader;

import java.io.IOException;

import java.io.InputStream;

/**

* @ClassName: MyClassLoader

* @Description:

* @author http://www.cnblogs.com/coe2coe/

* @date 2017年4月4日 下午9:52:47

*  

*/

public class MyClassLoader extends ClassLoader {

@Override

protected Class<?> findClass(String name) throws ClassNotFoundException {

//取得完整的class文件名。

String fullname = "test/" + name +".class";

System.out.println(fullname);

InputStream is = null;

Class clazz = null;

byte[] bytes = null;

try{

//读取class文件的内容。

is = MyClassLoader.class.getResourceAsStream(fullname);

int size = is.available();

bytes = new byte[size];

is.read(bytes);

//定义类。

    clazz = super.defineClass(bytes, 0, size);

}catch(Exception e){

e.printStackTrace();

}finally{

if(is!=null){

try {

is.close();

is = null;

} catch (IOException e) {

e.printStackTrace();

}

}

if(bytes!=null){

bytes = null;

}

}

return clazz;

}

}

测试代码如下:

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

Class  clazz = null;

ClassLoader loader = null;

MyClassLoader classLoader = new MyClassLoader();

loader = classLoader;

while(loader!=null){

System.out.println(loader.getClass().getName());

loader = loader.getParent();

}

System.out.println(loader);

System.out.println("-------------");

//类的完整的全限定名称//

//clazz = classLoader.loadClass("com.test.javatechnology.classloader.test.Sample");

//只写了简单名称。正常情况下无法加载。但是MyClassLoader做了特殊处理,从而可以成功加载。

clazz = classLoader.loadClass("Sample");

loader = clazz.getClassLoader();

while(loader!=null){

System.out.println(loader.getClass().getName());

loader = loader.getParent();

}

System.out.println(loader);

}

运行结果如下:

com.test.javatechnology.classloader.MyClassLoader

sun.misc.Launcher$AppClassLoader

sun.misc.Launcher$ExtClassLoader

null

-------------

test/Sample.class

com.test.javatechnology.classloader.MyClassLoader

sun.misc.Launcher$AppClassLoader

sun.misc.Launcher$ExtClassLoader

null

对运行结果分析如下:

(1)由于不在同一个包下,Java自带的类加载器AppClassLoader和ExtClassLoader以及Bootstrap类加载器均不可能找到Sample类的class文件。根据loadClass()方法的处理流程,此时将执行MyClassLoader的findClass()方法。

(2)MyClassLoader的findClass()方法中,成功找到并读取到了Sample类的class文件,再调用defineClass()方法完成对Sample类的定义,从而成功加载了不在同一个包下的另外一个类Sample类。

时间: 2024-12-20 16:07:39

Java重要技术(29)类加载器之类加载器的职责的相关文章

Java重要技术(28)类加载器之类加载器的层次关系和委托加载机制

1.1. 类加载器的层次 类加载器包括三种: Bootstrap ClassLoader:用于加载JRE的lib目录下的jar文件中的class. ExtClassLoader:用于加载JRE的lib/ext目录下的jar文件中的class. AppClassLoader:用于加载classpath下的class. 在加载一个class时,通常应该先委托给parent类加载器来加载,parent类加载器找不到这个类时,才自行加载.实际优先次序从高到低排列是BootStrap ClassLoade

java之 ------ JUnit、注解、类加载器

JUnit软件测试技术(工具) 在项目中建立专门用户测试的包结构. 在Junit中,通过@Test注解,可以运行一个方法(鼠标放在选择要运行的方法名上,单击右键,选择Run As,再选择JUnit Test即可). 这样做的好处就是不用在主代码中添加测试代码,避免了代码的冗余.而且一个测试类,可以测试多项功能,不需要main方法. 一. Junit注解说明 使用了@Test注解应该满足以下条件: 1) 必须是无参数的非静态方法. 2) 添加@Test注解的类,必须拥有一个无参数的公开构造 pac

Java虚拟机笔记 – JVM 自定义的类加载器的实现和使用2

1.用户自定义的类加载器: 要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用. findClass protected Class<?> findClass(String name) throws ClassNotFoundException 使用指定的二进制名称查找类.此方法应该被类加载器的实现重写,该实现按照委托模型来加载类.在通过父

Java虚拟机笔记 – JVM 自定义的类加载器的实现和使用

1.用户自定义的类加载器: 要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用. findClass protected Class<?> findClass(String name) throws ClassNotFoundException 使用指定的二进制名称查找类.此方法应该被类加载器的实现重写,该实现按照委托模型来加载类.在通过父

深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题

一.概述 定义:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的java类型.类加载和连接的过程都是在运行期间完成的. 二. 类的加载方式 1):本地编译好的class中直接加载 2):网络加载:java.net.URLClassLoader可以加载url指定的类 3):从jar.zip等等压缩文件加载类,自动解析jar文件找到class文件去加载util类 4):从java源代码文件动态编译成为class文件 三.类加载的时机

虚拟机类加载机制--类加载器

准备阶段的"通过一个类的全限定名来获取描述此类的二进制字节流"这个动作放到了Java虚拟机外部去实现,以便让应用程序自己决定如何如获取所需要的类.实现这个动作的代码模块称为"类加载器" 1.类与类加载器 每一个类加载器都有一个独立的类名称空间,由类加载器和类一起合作才能确定一个类在虚拟机中的唯一性.也就是说:比较两个类是否"相等",即使他们来自同一个Class文件,在同一个虚拟机上被加载,如果加载它们的类加载器不同,那么这两个类就不相等. 这里的

类加载和类加载器

什么是类加载 类加载指的是将.Class文件读入内存,并为之创建一个java.lang.Class对象,也就是说程序使用任何类时,系统都会为之建立一个java.lang.Class对象 何时类加载和类加载步骤 当程序主动使用某个类时,系统会通过加载,连接,初始化三个步骤来对该类进行初始化,JVM将会连续完成这三个步骤,也把这三个步骤统称为类加载或类初始化. 主动触发类加载的情况 1)创建类的实例,也就是new一个对象 2)访问某个类或接口的静态变量,或者对该静态变量赋值 3)调用类的静态方法 4

java 测试开发基础知识(类加载,JVM等)

写在开头: 面试的时候别人很可能会问你的java原理,.class load 原理, jvm机制,这些都是Java的底层知识,特整理如下: 1. 首先,编写一个java程序,大家会用ide编写一个例如helloworld.java的文件, 程序是能够识别这个文件的,但是计算机不行,所以需要一个编译的过程: 执行java.exe , 例如 在cmd的窗口执行:   $java  helloworld.java , 这个时候你会发现在同级目录系生成了一个helloworld.class的可执行文件,

转--深入JVM系列(三)之类加载、类加载器、双亲委派机制与常见问题

深入JVM系列(三)之类加载.类加载器.双亲委派机制与常见问题 http://blog.csdn.net/vernonzheng/article/details/8461380 转--深入JVM系列(三)之类加载.类加载器.双亲委派机制与常见问题