黑马程序员技术交流社区

标题: 类加载器 [打印本页]

作者: wumuzhong    时间: 2013-10-2 21:28
标题: 类加载器
-》简要介绍什么是累加器和类加载器的作用
-》java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap,ExtClassLoader,AppClassLoader
-》类加载器也是java类,因为其他是java类的类加载器本身也要被类加载器加载,显然必须有第一个加载器不是java类,这正是BootStrap
-》java虚拟机中的所有类装载器采用具有父子关系的属性结构进行
类加载器之间的父子关系和管辖范围图
父子关系:AppClassLoader->ExtClassLoader->BootStrap
关系范围:
BootStrap--->JRE/lib/rt.jar
ExtClassLoader--->JRE/lib/ext/*.jar
AppClassLoader--->CLASSPATH指定的所有jar或目录
类加载器的委托机制
-》当java虚拟机要加载一个类时,到底派出那个类加载器去加载呢?
-》》首先当前线程的类加载器去加载线程中的第一个类
-》》如果类A中引用了类B,java虚拟机将使用加载类A的类装载器来加载类B
-》》还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类
-》每个类加载器加载类时,又先委托给其上级类加载器
-》》当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加在不了,则抛出ClassNotFoundException,不是再去找发起者类加载的儿子,因为没有getChild方法,即使有,那有多个子类,找那个?
编写自己的类加载器
知识讲解
-》自定义的类加载器必须继承ClassLoader
-》loadClass方法与findClass方法,得到class文件转换成字节码
-》defineClass方法
编程步骤
-》编写一个对文件内容进行简单加密的程序
-》编写一个自己的类装载器,可实现对加密过的类进行装载和解密
-》编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类,程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName
实验步骤
-》对不带报名的class文件进行加密,加密结果存放到另外一个目录,例如:java MyClassLoader MyTest.class F:\itcast
-》运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast
-》用加密后的类文件替换CLASSPATH环境下的类文件,再执行上一步操作就出问题了,错误说明是AppClassLoader类装载器装载失败
-》删除CLASSPATH环境下的类文件,再执行上一步操作就没问题了。
实例代码:
public class ClassLoaderAttachment extends Date {
public String toString(){
  return "hello,itcast";
}
}


public class ClassLoaderTest {
/**
  * @param args
  */
public static void main(String[] args) throws Exception {
  // TODO Auto-generated method stub
  System.out.println(
    ClassLoaderTest.class.getClassLoader().getClass().getName()
    );
  System.out.println(
    System.class.getClassLoader()
    );
  System.out.println("xxx");
  ClassLoader loader = ClassLoaderTest.class.getClassLoader();
  while(loader != null){
   System.out.println(loader.getClass().getName());
   loader = loader.getParent();
  }
  System.out.println(loader);
  
  //System.out.println(new ClassLoaderAttachment().toString());
  System.out.println("xxx2");
  Class clazz = new MyClassLoader("itcastlib").loadClass("cn.itcast.day2.ClassLoaderAttachment");
  Date d1 =  (Date)clazz.newInstance();
  System.out.println(d1);
}
}


public class MyClassLoader extends ClassLoader{
/**
  * @param args
  */
public static void main(String[] args) throws Exception {
  // TODO Auto-generated method stub
  String srcPath = args[0];
  String destDir = args[1];
  FileInputStream fis = new FileInputStream(srcPath);
  String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
  String destPath = destDir + "\\" + destFileName;
  FileOutputStream fos = new FileOutputStream(destPath);
  cypher(fis,fos);
  fis.close();
  fos.close();
}

private static void cypher(InputStream ips ,OutputStream ops) throws Exception{
  int b = -1;
  while((b=ips.read())!=-1){
   ops.write(b ^ 0xff);
  }
}
private String classDir;
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
  // TODO Auto-generated method stub
  String classFileName = classDir + "\\"  + name.substring(name.lastIndexOf('.')+1) + ".class";
  try {
   FileInputStream fis = new FileInputStream(classFileName);
   ByteArrayOutputStream  bos = new ByteArrayOutputStream();
   cypher(fis,bos);
   fis.close();
   System.out.println("aaa");
   byte[] bytes = bos.toByteArray();
   return defineClass(bytes, 0, bytes.length);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return null;
}

public MyClassLoader(){
  
}

public MyClassLoader(String classDir){
  this.classDir = classDir;
}
}



作者: wumuzhong    时间: 2013-10-2 21:29
沙发,沙发,顶起




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2