zoukankan      html  css  js  c++  java
  • 45_自定义类加载器的编写原理分析

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

     

    image

     

    image

     

     

    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("
    *******查看类加载器的层次结构关系"); 
            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); 
        } 
      }
  • 相关阅读:
    主线程和子线程的区别
    正则表达式 之 常用实例
    Asp.Net 之 未能加载文件或程序集 system.web.extensions 解决方法
    .Net 与 Java 的服务接口相互调用
    C# 之 SqlConnection 类
    ADO.Net 之 数据库连接池(一)
    C# 之 DataReader 和 DataSet 的区别
    Asp.Net 之 缓存机制
    IIS 之 失败请求跟踪规则
    IIS 之 HTTP错误信息提示
  • 原文地址:https://www.cnblogs.com/qq-757617012/p/4273468.html
Copyright © 2011-2022 走看看