编写自己的classloader加载加密过的class

1 编写一个类,该类继承Date类:

package erica.classloader;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;

public class ClassLoaderAttachment extends Date {

 @Override
 public String toString() {
       return "hello erica";
  } 

}

 

 

2 编写一个类,该类可以使得加载的class文件,生成的class文件放在D:\itunes

package erica.classloader;

import java.io.*;

public class MyClassLoader {

 

 public static  void cypher(InputStream in,OutputStream out) throws IOException{
      int b=-1;
      while((b=in.read())!=-1){
       out.write(b^0xff);
  }
  
 }
 

}

3 运行生成加密以后的class

public static void main(String[] args) throws Exception {
      String srcPath="D:/workspace/WorkSpaceSpring/ReflectTest/bin/erica/classloader/ClassLoaderAttachment.class";
      String descPath="D:\\itunes\\ClassLoaderAttachment.class";
      FileInputStream fis=new  FileInputStream(srcPath);
      FileOutputStream fos=new  FileOutputStream(descPath);
      cypher(fis,fos);
      System.out.println("success");
 }

 

 

 

4 把生成的class覆盖原始的那个类的class文件,然后用java虚拟机特定的classloader去加载文件会报错。

package erica.classloader;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;

public class ClassLoaderAttachment extends Date {

 @Override
 public String toString() {
       return "hello erica";
 } 
 
 
 public static void main(String[] args) throws Exception {

  ClassLoaderAttachment  ca=new ClassLoaderAttachment();
   System.out.println(ca);
 }
 
}

报错如图所示:

5 那么就的我们自己的写的类加载器去加载加密的class了.

   1:继承ClassLoader类

   2:覆盖   protected  Class<?>findClass(String name)throws ClassNotFoundException 方法

   3:调用defineClass,将一个 byte 数组转换为 Class 类的实例,该实例就是加载一串二进制字节码的Class的对象

public class MyClassLoader extends ClassLoader{

 

private String dir;
 
 public MyClassLoader(){
  
 }
 
     public MyClassLoader(String dir){
        this.dir=dir;
 }

 

 @Override
  protected  Class<?>findClass(String name)throws ClassNotFoundException{
         System.out.println("findClass");
         String classname=dir+"/"+name+".class";
         FileInputStream fis;
  try {
          fis = new  FileInputStream(classname);
         ByteArrayOutputStream out=new ByteArrayOutputStream();
         cypher(fis,out); 
         fis.close();
         byte[]bytes=out.toByteArray();
         return defineClass(null,bytes,0,bytes.length);
  } catch (Exception e) {
       e.printStackTrace();
  }
  
      return null;
  }

 

}

 

 

6:用自己的类加载器加载自己的字节码

public static void main(String[] args) throws Exception {
  
       MyClassLoader  loader=new MyClassLoader("erica");
       Date d=(Date)loader.loadClass("ClassLoaderAttachment").newInstance();
       //Date d=(Date)loader.loadClass("erica.classloader.ClassLoaderAttachment").newInstance();//会去加载原始的class,因为指定了包名+类名
       System.out.println(d); 
  
 }
 

打印结果:

findClass
hello erica

打印出findClass字符串说明运行了自己的类加载器。

 

 

下面是jdk文档的自己编写类加载器的示例:

例如,应用程序可以创建一个网络类加载器,从服务器中下载类文件。示例代码如下所示:

   ClassLoader loader = new NetworkClassLoader(host, port);
   Object main = loader.loadClass("Main", true).newInstance();
          . . .
 

网络类加载器子类必须定义方法 findClassloadClassData,以实现从网络加载类。下载组成该类的字节后,它应该使用方法 defineClass 来创建类实例。示例实现如下:

     class NetworkClassLoader extends ClassLoader {
         String host;
         int port;

         public Class findClass(String name) {
             byte[] b = loadClassData(name);
             return defineClass(name, b, 0, b.length);
         }

         private byte[] loadClassData(String name) {
             // load the class data from the connection
              . . .
         }
     }

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值