自定义类的加载器,进行加密操作

  1. 为什么要自定义一个类的加载器呢,其实主要是由于,Java代码可以轻易的被反编译,如果你需要把自己的代码进行加密以防止反编译,可以先将编译后的代码用某种加密算法加密,类加密后就不能再用Java的ClassLoader去加载类了,这时就需要自定义ClassLoader在加载类的时候先解密类,然后再加载。
  2. 简单说一下有几种类的加载器,在jdk中有三种类的加载器
    引导类的加载器(BootStrap):加载“JAVA_HOME/jre/lib//rt.jar”这个jar包里面的类,比如Date String 等;
    扩展类的加载器(exe):加载 “JAVA_HOME/jre/lib/exe/*.jar”这个路径下的所有jar包中的类的;
    应用类加载器(app):加载类路径下的所有class。
  3. 接下来是一些代码来演示将一个类加密再用自己定义的类的加载器进行解密并运行的过程

    ①. 首先定义一个类我们用Man来做

package com.classloader;

public class Man {
    public static void run(){
        System.out.println("走你>>>>>>>....");
    }
}

②. 定义一个类用,在其中定义静态static方法,用来将以上代码(即刚写的Man类)所生成的.class文件进行加密,和解密

package com.classloader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class Encrypt {
        //简单的输入输出操作
        public static void coding(File src,File dest) throws Exception{
            InputStream is = new FileInputStream(src);
            OutputStream os = new FileOutputStream(dest);
            int data;
            while((data=is.read())!=-1){
                data = encryptAndDecrypt(data);
                os.write(data);
            }
            //原来的.class文件删除
            src.delete();
            is.close();
            os.close();
        }
        //将计算机在.class文件中读到的每一个字节进行加密操作,当然了解密也是用这个方法,因为A^n^n==A
        public static int encryptAndDecrypt(int data){
            return data^("这是密码".hashCode());
        }
}

③. 编写自己。自定义的类的加载器,需要继承ClassLoader类,并重写findClas方法

package com.classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {
    // 加载类的路径
    private String path;

    public MyClassLoader(String path) {
        super();
        this.path = path;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
    //其实这个name是类的全路径名
        try {
            //获得class的名称
            name = name.substring(name.lastIndexOf(".")+1);
            //这里其实是编辑新的文件的文件名称,因为我将会把电脑生成的class文件,用io的方式重新,写到自定义类的加载器要加载的路径下面,这里的path就是该路径,其中所有的文件名称都将会是,[类的名称+".amm"]的形式(.amm,是我的博客名称缩写,这里作为文件后缀了)
            File file = new File(path + name + ".amm");
            //将class文件写入内存
            InputStream is = new FileInputStream(file);
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            int len;
            while ((len = is.read()) != -1) {
                //重新进行解码
                bo.write(Encrypt.encryptAndDecrypt(len));
            }
            is.close();
            byte[] byteArray = bo.toByteArray();
            //找到类
            Class<?> defineClass = defineClass(null,byteArray, 0, byteArray.length);
            return defineClass;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return super.findClass(name);
    }

}

④. 编写测试类进行,对自定义的类的加载器进行测试

package com.classloader;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        //对正常的类进行加密操作
        //这里是计算机自己产生的正常的lass路径
        File src = new File("D:\\develop\\eclipse-jee-mars-2-win32\\servlet\\ClassLoader\\bin\\com\\classloader\\Man.class");
        File dest = new File("class_loader_test/Man.lhy");
        Encrypt.coding(src, dest);


        ClassLoader myClassLoader = new MyClassLoader("class_loader_test/");
        Class<?> loadClass = myClassLoader.loadClass("com.classloader.Man");

        ClassLoader loader = loadClass.getClassLoader();
        System.out.println("==="+loader);  //打印加载器的名称,如果是自定义加载器架加载的该文件,则会出现该加载器的名称(这里是我运行出来的结果===com.classloader.MyClassLoader@888e6c)

        Method method = loadClass.getMethod("run", null);
        method.invoke(loadClass.newInstance(),null);
    }
}

④.运行结果

这里写图片描述

以上则是我的理解。希望我们都在变成大牛的路上一去不复返,我爱你ლ(′◉❥◉`ლ)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java自定义的一个简单的示例代码如下: public class MyClassLoader extends ClassLoader { 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 } } ### 回答2: Java自定义代码样例如下: ```java import java.io.*; public class MyClassLoader extends ClassLoader { private String path; // 类的路径 public MyClassLoader(String path) { this.path = path; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] data = loadClassData(name); return defineClass(name, data, 0, data.length); } private byte[] loadClassData(String name) { try { FileInputStream fis = new FileInputStream(new File(path + name + ".class")); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int len; while ((len = fis.read()) != -1) { baos.write(len); } fis.close(); return baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return null; } } ``` 使用自定义类: ```java public class Main { public static void main(String[] args) throws Exception { MyClassLoader classLoader = new MyClassLoader("类路径"); Class<?> clazz = classLoader.loadClass("com.example.TestClass"); // TestClass类 Object obj = clazz.newInstance(); // 创建TestClass实例 // 使用obj进行操作,调用方法等 } } ``` 以上是一个简单的自定义的代码样例。我们可以根据实际需求,通过自定义来实现更复杂的功能,如加密/动态生成的类文件,实现类文件的热等。 ### 回答3: 自定义是指通过继承ClassLoader类并重写其中的方法来实现自己的类。下面是一个简单的Java自定义的代码示例: ```java import java.io.*; public class MyClassLoader extends ClassLoader { // 自定义需要指定类文件的路径 private String classPath; public MyClassLoader(String classPath) { this.classPath = classPath; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { // 将类文件转换成字节流 byte[] data = loadClassData(name); // 调用父类的defineClass方法创建类对象 return defineClass(name, data, 0, data.length); } private byte[] loadClassData(String className) { try { // 类文件的完整路径 String path = classPath + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; InputStream inputStream = new FileInputStream(new File(path)); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; // 读取类文件并写入内存中 while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } inputStream.close(); outputStream.close(); // 返回字节流 return outputStream.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return null; } public static void main(String[] args) { // 实例化自定义并指定类文件路径 MyClassLoader classLoader = new MyClassLoader("路径"); try { // 使用自定义类 Class<?> clazz = classLoader.loadClass("类名"); // 可以对的类进行操作 // ... } catch (ClassNotFoundException e) { e.printStackTrace(); } } } ``` 这个自定义首先需要重写`findClass`方法,在该方法中通过`loadClassData`方法将类文件读取为字节流,然后调用父类的`defineClass`方法创建类对象。 `loadClassData`方法根据指定的类文件路径将类文件读取为字节流,并将字节流写入ByteArrayOutputStream中,最后返回字节数组。 在示例代码的`main`方法中,实例化自定义并指定类文件路径,然后通过`loadClass`方法指定的类。可以在类后对其进行相关操作

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值