类加载器
来源:互联网 发布:史蒂夫纳什生涯数据 编辑:程序博客网 时间:2024/06/14 02:59
作用:当程序用到某个类中,由类加载器将类的字节码加载进内存。
JAVA虚拟机中可以安装多个加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader, AppClassLoader
xxx.class.getClassLoader.getClass( ).getName( );//获取某个类的类加载器的名称。
但是调用JAVA提供的类是由BootStrap加载器加载,底层加载器。用get.ClassLoader返回的是空。
类加载也是一个java类,因为其它是java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是JAVA类的,这正是BootStrap,由C++编写的。
类加载器之间的父子关系和管辖范围
BootStap JRE/lib/rt.jar(JAVA提供的类都在rt.jar包里)
ExtClassLoader JRE/lib/ext/*.jar(ext扩展jar包存放目录,如果把自己写的类导成jar包放到此目录下。会被ExtClassLoader加载器加载)
AppClassLoader ClassPath指定的所有jar或目录
(优先级问题:先父后子)
自定义类加载器,需要继承ClassLoader类,构造方法中需指定加载类的父类。默认有。
类加载器的委托机制
当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
1. 首先当前线程的类加载器去加载线程中的第一个类。
Thread类中有一个方法:setContextClassLoader(ClassLoader cl)。
2. 如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
3. 还可以直接调用ClassLoader.loadClass( )方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。
1. 当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFooundException,不是再去找发起者类加载器的子类了,因为没有getChild方法,即使有,那有多个子类,找哪一个呢?
2. 对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的itcast.jar包中后,运行结果为ExtClassLoader的原因。
面试题:我们可以写一个java.lang.System包
答:通常是不可以的,因为如果我写一个System类放到ClassPath目录下,ClassPath目录下的类都是由AppClassLoader加载的,AppClassLoader会委托祖宗类,System在祖宗类中存在,会加载。所以根本不可能加载我的这个System类。不过有一种办法,就是我自己写一个类加载器,而这个类加载器不用委托祖宗类。
1.知识讲解:
自定义的类加载器的必须继承ClassLoader抽象类
loadClass()方法与findClass()方法,loadClass() 方法是去委托父类,我们自己写加载类只要覆盖findClass方法。
defineClass(String name)方法:将得到的class文件转换成字节码
2.编程步骤:
编写一个对文件内容进行简单加密的程序。
编写了一个自己的类装载器,可实现对加密过的类进行装载和解密。
编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类。程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName。
3.实验步骤:
对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如: java MyClassLoader MyTest.class F:\itcast
运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast
用加密后的类文件替换CLASSPATH环境下的类文件,再执行上一步操作就出问题了,错误说明是AppClassLoader类装载器装载失败。
删除CLASSPATH环境下的类文件,再执行上一步操作就没问题了。
MyClassLoader.java
package cn.test;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class MyClassLoader extends ClassLoader {/** * @param args */// public static void main(String[] args) throws Exception {// // TODO Auto-generated method stub// String sourceFilePath = args[0];// String targetDir = args[1];// String myPath = MyClassLoader.class.getResource("").getPath();// String[] path = myPath.split("bin");// String targetFilePath =// path[0]+targetDir+"\\"+sourceFilePath.substring(sourceFilePath.lastIndexOf('\\')+1);//// InputStream is = new FileInputStream(sourceFilePath);// OutputStream os = new FileOutputStream(targetFilePath);//// encrypt(is,os);// }public static void encrypt(InputStream is, OutputStream os) {int by = -1;try {while ((by = is.read()) != -1) {os.write((byte) by * 0xff);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private String classPath;@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {// TODO Auto-generated method stubtry {InputStream is = new FileInputStream(classPath + File.separator+ name + ".class");ByteArrayOutputStream baos = new ByteArrayOutputStream();encrypt(is, baos);byte[] bytes = baos.toByteArray();return defineClass(bytes, 0, bytes.length);} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}return super.findClass(name);}public MyClassLoader() {// TODO Auto-generated constructor stub}public MyClassLoader(String classPath) {this.classPath = classPath;}}
MyClassTest.java 测试类
package cn.test;public class MyClassTest {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubtry {Class clazz = new MyClassLoader("myclasslib").loadClass("MyClass");Object obj = clazz.newInstance();System.out.println(obj.toString());System.out.println("====================================");ClassLoader clazzLoader = obj.getClass().getClassLoader();while (clazzLoader != null) {System.out.println(clazzLoader.getClass().getName());clazzLoader = clazzLoader.getParent();}if (clazzLoader == null)System.out.println("BootStrap");} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
- 加载、类加载、类加载器
- 类加载机制及类加载器加载Class流程
- 类加载器---类加载器简介
- Java类加载器加载类顺序
- 类加载器---类加载机制
- Java类加载器加载类顺序
- Java类加载器加载类顺序
- Java类加载器加载类顺序
- 类加载器和类加载机制
- 使用类加载器加载配置文件
- 用类加载器加载配置文件
- 用类加载器加载配置文件
- 类加载器的加载机制
- 用java类加载器加载资源
- 扩展类加载器的加载问题
- java类加载器的加载顺序
- 使用类加载器加载配置文件
- Java 类加载器以及加载机制
- 安装sybase出现 找不到JVM错误请使用选项 -is:javahome<JAVA HOME DIR>
- 为什么支付宝使用用户体验欠佳的安全控件,而国外 Paypal、Google Checkout 都没有这种的设计?
- java比较器Comparator
- 块设备驱动之nandflash——简单程序分析
- 块设备驱动之nandflash——支持分区
- 类加载器
- 笔尖上的人生开始……
- norflash驱动程序——基础知识
- 内核自带norflash的编译与实验
- IO_STACK_LOCATION 结构
- norflash驱动编写
- java SWing事件调用的两种机制
- linux网络驱动体系结构
- opencv 提取感兴趣区域 (新版方法)