45_自定义类加载器的编写原理分析

  • 知识讲解
    • 自定义的类加载器必须继承ClassLoader
    • loadClass方法与findClass方法
    • defineClass方法
  • 编程步骤
    • 编写一个对文件内容进行简单加密的程序。
    • 编写一个自己的类加载器,可实现对加密过得类进行加载和解密。
    • 编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类。程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName。
  • 实验步骤:
    • 对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如:java MyClassLoader MyTest.class F:\itcast
    • 运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast

 

45_自定义类加载器的编写原理分析

 

45_自定义类加载器的编写原理分析

 

 

package com.itcast.day3;

import java.io.ByteArrayOutputStream; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.io.OutputStream; 
/** 
* 1 加载 
* 2 加密 
* 3 自定义类加载 
* @author hp 
* 
*/ 
public class MyClassLoader extends ClassLoader{ 
    public static void main(String[] args) throws Exception{ 
        String srcPath=args[0]; 
        String destDir=args[1]; 
        
        //加载.class,加密.class,写到自定义目录 
        FileInputStream fis=new FileInputStream(srcPath); 
        String destPath=destDir+"\\"+srcPath.substring(srcPath.lastIndexOf("\\")); 
        FileOutputStream fos=new FileOutputStream(destPath); 
        cyp(fis,fos); 
        fis.close(); 
        fos.close(); 
    } 
    /** 
     * 加密 or 解密 
     * @param ips 
     * @param ops 
     * @throws Exception 
     */ 
    private static void cyp(InputStream ips,OutputStream ops)throws Exception{ 
        int b=-1; 
        while((b=ips.read())!=-1){ 
            ops.write(b^0xff); 
        } 
    } 
    
    
    
    private String fileDir;//.class文件路径 
    
    /** 
     * 自定义类加载 
     */ 
    @Override 
    protected Class<?> findClass(String name) throws ClassNotFoundException { 
        String classFileName=fileDir+"\\"+name+".class"; 
        try { 
            FileInputStream fis=new FileInputStream(classFileName); 
            ByteArrayOutputStream bos=new ByteArrayOutputStream(); 
            cyp(fis,bos); 
            fis.close(); 
            byte[] bytes=bos.toByteArray(); 
            return defineClass(bytes, 0, bytes.length); 
        }  catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return super.findClass(name); 
    } 
    
    public MyClassLoader(){ 
        
    } 
    public MyClassLoader(String fileDir){ 
        this.fileDir=fileDir; 
    } 
}

 

 

 

package com.itcast.day3;

import java.util.Date; 
/** 
* 要加载的类 
* @author liujl 
*继承自Date是因为方便接收newInstance返回值,不然写成ClassLoaderAttachment自己时,编译不通过(加密过) 
*/ 
public class ClassLoaderAttachment extends Date { 
    @Override 
    public String toString(){ 
        return "hello itcast"; 
    } 
}

 

package com.itcast.day3;

import java.util.Date;

/** 
* 类加载器测试 
* @author ljl 
* 
*/ 
public class ClassLoaderTest {

    public static void main(String[] args)throws Exception { 
        
        /** 
         * 01.逐一编写下列代码,说明放置在不同位置的类确实由不同的类加载器加载的。 
         */ 
        
        //sun.misc.Launcher$AppClassLoader 
        System.out.println(ClassLoaderTest.class.getClassLoader() 
                .getClass().getName()); 
        
        //Exception in thread "main" java.lang.NullPointerException 
        //报空指针,说明 ClassLoaderTest和System 这两个类实际存放位置不同,也确实不是同一个类加载器加载的 
        //System是由BootStrap加载的 
//        System.out.println(System.class.getClassLoader().getClass().getName()); 
        
        //null ,类加载器为null说明,不存在类加载器的java类实例,那么System一定是由jvm的核心加载器BootStrap负责加载 
        System.out.println(System.class.getClassLoader()); 
        
        
        
        /** 
         * 02.查看类加载器的层次结构关系 
         */ 
        System.out.println("\n*******查看类加载器的层次结构关系"); 
        ClassLoader loader=ClassLoaderTest.class.getClassLoader(); 
        while(loader!=null){ 
            System.out.println(loader.getClass().getName()); 
            loader=loader.getParent(); 
        } 
        System.out.println(loader); 
        
        /**运行结果 
         *  sun.misc.Launcher$AppClassLoader---孙子 
            sun.misc.Launcher$ExtClassLoader---爸爸 
            null--爷爷--BootStrap 
         */ 
        
        /** 
         * 03.使用自己定义的类加载器加载特定目录下的类 
         */ 
        //System.out.println(new ClassLoaderAttachment().toString()); 
        Class clazz=new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachment"); 
        Date d1=(Date)clazz.newInstance(); 
        System.out.println(d1); 
    } 
  }
开始做,坚持做,重复做
上一篇:Cocos2d-x 3.0 beta 版本创建项目


下一篇:百度地图开源库 BMaplib