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自带的类加载器AppClassLoader和ExtClassLoader以及Bootstrap类加载器均不可能找到Sample类的class文件。根据loadClass()方法的处理流程,此时将执行MyClassLoader的findClass()方法。
(2)MyClassLoader的findClass()方法中,成功找到并读取到了Sample类的class文件,再调用defineClass()方法完成对Sample类的定义,从而成功加载了不在同一个包下的另外一个类Sample类。
以上是关于Java重要技术(29)类加载器之类加载器的职责的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Dalvik 函数抽取加壳 ( 类加载流程分析 | ClassLoader#loadClass 函数分析 | BaseDexClassLoader#findClass 分析 )(代