• JAVA高新技术学习<三>


    /**
    * 类加载器
    * java类通过类加载器将类加载到虚拟机中,那么加载器又是谁来加载它呢?
    * 显然,根类加载器不是java类,是BootStrap 它嵌入在JVM的内核中
    * 他还有两个子的类加载器:ExtClassLoader和AppClassLoader
    * @author shantui *
    */

    //类加载器的包含关系:
        /*
        * null(BootStrap)>ExtClassLoader>AppClassLoader
        * AppClassLoader管辖范围:CLASSPATH指定的所有jar或目录 ,systemclassloader
        * ExtClassLoader管辖范围:JRE lib ext /  *.jar
        * BootStrap     管辖范围:JRE lib  rt.jar
        *
        * 自定义加载器,必须用我提供的加载器才能加载我放在指定目录下
        * 的类,实现加密功能。
        * 调用ClassLoader.Loadclass()来指定类加载器去加载某类。
        * 如果指定加载器去找某类,它不会直接找,而是直接溯源(委托机制)到BootStrap让
        * 它去找,如果他也没找到就推回来给子类找,再找不到再给子子类也就是最先
        * 发起溯源的那个类,只要又返回了发起者手里,还找不到就报异常,这样避免了字节码会多次加载的问题

    /**
    * 模版方法设计模式
    * 父类里面有个方法f,f里面有个细节流程定义为抽象方法F
    * 留待子类去完成
    * 子类1里面有自己独特的f1,子类2里面有独特f2     *
    */

    自定义加载器演示:

          要实现的功能:定义一个加密方法,读取包里的一个类文件的同时把从类文件读到的每个字节

    与或0xff,把这个类文件字节打乱,把加密好的类文件存放到指定的目录下面。

          自定义一个解密用的类加载器,限制虚拟机对默认类加载器的使用,而调用自定义的加载器,在加载被加密类的过程中,实现对类的解密。

          思路:定义一个加载器类,用来 实现读取类文件并加密,并实现对加密后的类进行加载并解密处理。

         定义一个被加密的类,用于演示加密和不加密的区别,只重写其toString方法,打印演示

         定义一个解密类,运行此类可以调用解密方法。

          加载器类代码:

       1: package jiami;
       2:  
       3: public class ClassLoaderTest 
       4: {
       5:     public static void main(String[] args) throws Exception
       6:     {
       7:         //看一下我们新建的这个类是谁加载的
       8:         //System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());
       9:     
      10:     ClassLoader loader = ClassLoaderTest.class.getClassLoader();
      11:     //看一下我们新建的这个类的父亲都是谁(null就是那个内核根加载器)
      12:     while(loader!=null)
      13:     {
      14:         System.out.println(loader.getClass().getName());
      15:         loader =loader.getParent();
      16:     }
      17:     System.out.println(loader);    
      18:     }
      19: }

    定义一个被加密的类,用于演示加密和不加密的区别

       1: package jiami;
       2:  
       3: public class JiaMiDiaoYong {
       4:  
       5:     /**
       6:      * @param args
       7:      */
       8:     public static void main(String[] args) {
       9:         // TODO Auto-generated method stub
      10:         //调用一下加密过的类ClassLoaderAttachment,发现已经无法编译了 。加密成功
      11:          //new ClassLoaderAttachment().toString();
      12:  
      13:     }
      14:  
      15: }

    定义自定义加载器类,在main方法里实现以下功能:

    把要加密的类加密后存入指定文件夹中;

    利用自定义的加载器去加装加密后的类,并解密,生成一个新的类文件

    代码如下:

       1: package jiami;
       2: import java.io.ByteArrayOutputStream;
       3: import java.io.FileInputStream;
       4: import java.io.FileNotFoundException;
       5: import java.io.FileOutputStream;
       6: import java.io.InputStream;
       7: import java.io.OutputStream;
       8:  
       9: public class myClassLoader extends ClassLoader 
      10: {
      11:     public myClassLoader(){}    
      12:     public myClassLoader(String classDir)
      13:     {
      14:         this.classDir=classDir;
      15:     }
      16: public static void main(String[] args) throws Exception
      17: {
      18:     
      19:     //源 地址通过eclipse软件人为设定为args[0]
      20:     String srcPath = args[0];//传来的第一个值就是源路径
      21:     String destDir = args[1];//传来的第二个就是目的路径
      22:     //定义文件读取流 对象,关联要被加密的类文件地址。
      23:     FileInputStream fis =new FileInputStream(srcPath);
      24:     //定义生产的加密文件的名字,还是和原来的文件名一样,通过截取源路径最后的文件名形式
      25:     String destFileName=srcPath.substring(srcPath.lastIndexOf('\\')+1);
      26:     //定义被加密后文件要存放的路径:文件夹/类文件名
      27:     String destPath=destDir+"\\"+destFileName;
      28:     //定义文件读取流对象,关联到要输出的路径
      29:     FileOutputStream fos = new FileOutputStream (destPath);
      30:     //把读取到的类文件输入流加密后,返回已写入了加密内容的类文件的输出流
      31:     cypher(fis,fos);
      32:     //关闭两个流对象
      33:     fis.close();    
      34:     fos.close();   
      35: } 
      36: //加密函数
      37: private static void cypher(InputStream  ips ,OutputStream ops)throws Exception
      38: {
      39:     int b =-1;
      40:     while ((b=ips.read())!=-1)
      41:     {
      42:         ops.write(b ^ 0xff);         
      43:     }
      44: }
      45:  
      46:  
      47: private String classDir;
      48: //自定义一个类加载器
      49: @Override//覆盖其findClass方法,不让其传递给父类,自己找
      50:     protected Class<?> findClass(String name) throws ClassNotFoundException {
      51:         // TODO Auto-generated method stub
      52:     //拼出要加载的已加密并放在另一个文件夹中的类文件的路径
      53:     String classFileName=classDir+"\\"+name+".class";
      54:     //读取系统上的文件要进行异常处理
      55:     try {        
      56:         //定义读取流对象关联要解密的类文件
      57:         FileInputStream fis =new FileInputStream(classFileName);
      58:         //定义一个字节数组输出流,用以缓存解密后的字节文件    ,数据缓冲专用流,数组不可以用以做缓冲区    
      59:         ByteArrayOutputStream bos=new ByteArrayOutputStream();
      60:         //加密和解密一个函数
      61:         cypher(fis,bos);
      62:         //关流
      63:         fis.close();
      64:         //把缓冲区里的字节存入字节数组中
      65:         byte[] bytes=bos.toByteArray();
      66:         //利用defineClass方法,把字节数组 转换为类文件
      67:         return defineClass(null,bytes,0,bytes.length);
      68:         
      69:         
      70:     }
      71:     catch (Exception e) {
      72:         // TODO Auto-generated catch block
      73:         e.printStackTrace();
      74:     }
      75:         return super.findClass(name);//若子类搞不定,否就返回父类的,让父类去找 
      76:     
      77:     }
      78: }

    定义一个加密器,运行即可对指定类文件加密

       1: package jiami;
       2:  
       3: public class JiaMiDiaoYong {
       4:  
       5:     /**
       6:      * @param args
       7:      */
       8:     public static void main(String[] args) {
       9:         // TODO Auto-generated method stub
      10:         //调用一下加密过的类ClassLoaderAttachment,发现已经无法编译了 。加密成功
      11:          //new ClassLoaderAttachment().toString();
      12:  
      13:     }
      14:  
      15: }

    定义一个解密器,运行即可对加密过的文件解密

       1: package jiami;
       2:  
       3: import java.util.Date;
       4:  
       5: public class JieMiDiaoYong {
       6:  
       7:     /**
       8:      * @param args     * 
       9:      */
      10:     public static void main(String[] args) throws Exception {
      11:         // TODO Auto-generated method stub
      12:         Class clazz= new myClassLoader("ItClassLib").loadClass("ClassLoaderAttachment");
      13:         //此时返回值的类型不能写ClassLoaderAttachment,因为它已经被加密搞烂了,所以
      14:         //返回值类型只能用它的父类来装一下
      15:         Object d1=(Object)clazz.newInstance();
      16:         System.out.println(d1);
      17:     }
      18:  
      19: }
  • 相关阅读:
    Android AsyncTask
    android 自定义 view 和 ViewGroup
    Android Acitivity 生命周期
    Android Service 与 IntentService
    Android LocalBroadcastManager 与 BroadcastReceiver
    如何提升 service 等级,不被kill(整合)
    Android 插件开发,做成动态加载
    新提交审核app保留检查更新入口将被拒绝(读取App Store 版本号的)
    Android: Service中创建窗口显示
    如何升级PowerShell
  • 原文地址:https://www.cnblogs.com/94007boy/p/2695578.html
Copyright © 2020-2023  润新知