类加载器的委托机制、自定义类加载器
2014-06-22 18:29
267 查看
** * 类加载器 1、每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的 类装载器去加载类,这就是类加载器的委托模式。 2、类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的 类时, 然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装 载器时, 如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异 常。 3、当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢? 首先当前线程的类加载器去加载线程中的第一个类。 因为线程中有自己的类加载器,线程中的类都可以指定自己的类加载器。 如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。 4、每个类加载器加载类时,又先委托给其上级类加载器。 当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛 ClassNotFoundException,不是再去找发起者类加载器的儿子, 因为没有getChild 方法,即使有,那有多个儿子,找哪一个呢? 5、对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest 输出成 jre/lib/ext目录下的itcast.jar包中后,运行结果为 ExtClassLoader的原因。 自定义类加载器 知识讲解: 自定义的类加载器的必须继承ClassLoader loadClass方法与findClass方法 defineClass方法 编程步骤: 编写一个对文件内容进行简单加密的程序。 编写了一个自己的类装载器,可实现对加密过的类进行装载和解密。 编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量, 因为编译器无法识别这个类。程序中可以除了使用ClassLoader.load方法之外, 还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName。 实验步骤: 对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如: java MyClassLoader MyTest.class F:\itcast 运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast 用加密后的类文件替换CLASSPATH环境下的类文件,再执行上一步操作就出问题了,错误说明是AppClassLoader类装载器装载失败。 * */ /**在项目下建一个文件夹,把未加密 的目标class文件 加密并写入该文件夹 * 然后用该类解密该文件,获取该字节码文件对象 * @author yaomaokai * */ import java.io.*; public class MyClassLoader extends ClassLoader { public static void main(String[] args) throws Exception { String srcPath = args[0]; //截取文件名 String fileNmae = srcPath.substring(srcPath.lastIndexOf("\\") + 1); //目标路径 String destDir = args[1]; //目标路径+截取的文件名组成目标绝对路径 String destPath = destDir + "\\" + fileNmae; FileInputStream fis = new FileInputStream(srcPath); FileOutputStream fos = new FileOutputStream(destPath); //加密 syhpern(fis, fos); fis.close(); fos.close(); } //输入流加密到输出流 private static void syhpern(InputStream ips, OutputStream ops) throws Exception { int b = 0; while ((b = ips.read()) != -1) {//加密后写入输出流 ops.write(b ^ 0xff); } } private String classPath; public MyClassLoader() { } //类加载器传入目标路径 public MyClassLoader(String classPath) { this.classPath = classPath; } @Override//传入一个字节码文件名,重写父类的findClass方法,返回该类的字节码文件对象 protected Class<?> findClass(String name) throws ClassNotFoundException { String classFileName=classPath+"\\"+name+".class"; try { //字节输入流读取未解密的文件 FileInputStream fis = new FileInputStream(classFileName); System.out.println(classFileName); //字节数组输出流 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //解密 syhpern(fis,bos); fis.close(); //字节输出流变成字节数据 byte[] buff= bos.toByteArray(); //传入该字节数组 返回字节码对象 return defineClass(buff, 0, buff.length); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // TODO Auto-generated method stub return null; } } 测试类 public class Test { /** * @param args * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException */ public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { MyClassLoader loader = new MyClassLoader("itcastlib"); Class clazz = loader.loadClass("Itheima"); Object obj =clazz.newInstance(); System.out.println(obj); } } |
相关文章推荐
- 黑马程序员——类加载器——委托机制、自定义类加载器
- 类加载器:认识类加载器、委托机制、自定义类加载器、一个类加载器的高级问题
- 类加载器和委托机制的理解
- java类加载器学习2――自定义类加载器和父类委托机制带来的问题
- 黑马程序员--05.类加载器--04【应用程序默认类加载器】【验证类加载器委托机制】
- java jvm类加载器-父亲委托机制实例分析
- 类加载器的委托机制
- 【类加载器】————类加载器之间的父子关系以及管辖范围【委托机制】
- 类加载器的父委托机制
- 黑马程序员_类加载器的委托机制
- JVM中类加载器的父委托机制
- 47、类加载器的父亲委托机制
- 类加载器的父亲委托机制
- java类加载器学习2——自定义类加载器和父类委托机制带来的问题/JAVA类加载的委托模型/Java的委托
- Java虚拟机JVM学习05 类加载器的父委托机制
- JVM中类加载器的父委托机制
- 类加载器的使用。和加载器的委托机制
- 类加载器的父亲委托机制深度详解
- jvm原理(6)类加载器双亲委托机制详解
- 解析Java虚拟机中类的初始化及加载器的父委托机制