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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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自带的类加载器AppClassLoaderExtClassLoader以及Bootstrap类加载器均不可能找到Sample类的class文件。根据loadClass()方法的处理流程,此时将执行MyClassLoaderfindClass()方法。

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

 

以上是关于Java重要技术(29)类加载器之类加载器的职责的主要内容,如果未能解决你的问题,请参考以下文章

Java基础之类加载器

Android 逆向Dalvik 函数抽取加壳 ( 类加载流程分析 | ClassLoader#loadClass 函数分析 | BaseDexClassLoader#findClass 分析 )(代

Java双亲委派模型

Java类加载器的工作原理

java类加载器的层次结构,自定义类加载器的步骤

深入JAVA虚拟机之类加载器