java classloader 加密_自定义ClassLoader进行class文件加密

本文介绍了如何创建一个自定义的Java ClassLoader,通过覆盖`findClass()`方法并在其中实现类文件的加密读取和解密加载,确保类文件的安全。详细展示了如何在`getClassByte()`方法中进行字节流加密解密操作,并提供了测试用例验证了加密ClassLoader的正确性。
摘要由CSDN通过智能技术生成

1.基础使用ClassLoader

1.1 创建自定义ClassLoader并继承ClassLoader

这里我只覆写了一个findClass方法(实际上可以覆写更多方法)因为在下文我需要达到加密class,需要覆写该findClass(),在该findClass里,调用了我自己写的一个method:getClassByte(),该方法的作用是读取class文件字节流,那么我们的加密手段,可以在该方法中做文章哈。当classData为空的时候,我们就交给super的方法处理(抛出ClassNotFound的异常),当classData不为空,那么我们就加载该类。

package classload;

import java.io.*;

/**

* @author Lczy-Huang

* @classname MyClassLoader

* @desc 自定义类加载器

* @date 2020-05-24 20:38

**/

public class MyClassLoader extends ClassLoader {

private String classPath;

private final static int BUFSIZE = 4096;

public MyClassLoader(String classPath){

this.classPath = classPath;

}

@Override

protected Class> findClass(String name) throws ClassNotFoundException{

try{

byte[] classData = getClassByte(name);

if(classData!=null){

return defineClass(name,classData,0,classData.length);

}

}catch (IOException e){

e.printStackTrace();

}

return super.findClass(name);

}

/***

* class字节流获取

*/

private byte[] getClassByte(String className) throws IOException{

String classRealPath = classPath + File.separatorChar + className.replace('.',File.separatorChar)+".class";

byte[] buf = new byte[BUFSIZE];

int len;

ByteArrayOutputStream out = null;

try(InputStream in = new FileInputStream(classRealPath);){

out = new ByteArrayOutputStream();

while ((len = in.read(buf))!=-1){

out.write(buf,0,len);

}

}catch (FileNotFoundException ex){

ex.printStackTrace();

}finally {

if(out!=null){

out.close();

}

}

if(out!=null){

return out.toByteArray();

}

return null;

}

}

2.ClassLoader测试

测试主类中,使用该类加载器进行加载我已经预先编译好的class文件,该文件不要存在运行项目之下,会导致系统加载器加载该文件,测试主类:

package classload;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

/**

* @author Lczy-Huang

* @classname MyClassLoaderTest

* @desc 测试类加载

* @date 2020-05-24 20:59

**/

public class MyClassLoaderTest {

public static void main(String []args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {

//自定义类加载器的加载路径

MyClassLoader myClassLoader=new MyClassLoader("C:\\Users\\Lczy-Huang\\Desktop");

//包名+类名

Class c=myClassLoader.loadClass("classload.MyClassLoaderTestClass");

if(c!=null){

Object obj=c.newInstance();

Method method=c.getMethod("test", null);

method.invoke(obj, null);

System.out.println(c.getClassLoader().toString());

}

}

}

可以看出MyClassLoader已经生效了,运行结果如下:

This is success

classload.MyClassLoader@12bb4df8

3. ClassLoader改造Secuity ClassLoader

3.1 加密解密类

这里只编写单字节的加密,所以一次读取一个字节,而后异或一个数作为加密。

package classload;

import java.io.*;

/**

* @author Lczy-Huang

* @classname EncrypClassFile

* @desc 加密class文件为eclass文件(自定义eclass区分class)

* @date 2020-05-24 23:07

**/

public class EncrypClassFile {

public static void encrypt(String src, String dest) throws IOException {

try(InputStream in = new FileInputStream(src);

OutputStream out = new FileOutputStream(dest);) {

int c = -1;

while ((c = in.read()) != -1) {

// 进行单字节加密

out.write(encryptAlgorithm(c));

}

} catch (Exception e) {

e.printStackTrace();

}

}

/***

* 单字节加密算法

*/

public static int encryptAlgorithm(int c){

return c ^ 0xff;

}

/***

* 单字节解密算法

*/

public static int decryptAlgorithm(int c){

return c ^ 0xff;

}

public static void main(String[] args) throws IOException {

encrypt("C:\\Users\\Lczy-Huang\\Desktop\\classload\\MyClassLoaderTestClass.class"

,"C:\\Users\\Lczy-Huang\\Desktop\\classload\\MyClassLoaderTestClass.eclass");

}

}

3.2 ClassLoader类改造

主要改造的是:getClassByte(),从每次获取BUFSIZE大小的数组变成每次获取单字节,而后进行解密,拼接的文件后缀,由于加密文件为eclass,所以这里也需要变成eclass。

package classload;

import java.io.*;

/**

* @author Lczy-Huang

* @classname MyClassLoader

* @desc 自定义类加载器

* @date 2020-05-24 20:38

**/

public class MyClassLoader extends ClassLoader {

private String classPath;

private final static int BUFSIZE = 4096;

public MyClassLoader(String classPath){

this.classPath = classPath;

}

@Override

protected Class> findClass(String name) throws ClassNotFoundException{

try{

byte[] classData = getClassByte(name);

if(classData!=null){

return defineClass(name,classData,0,classData.length);

}

}catch (IOException e){

e.printStackTrace();

}

return super.findClass(name);

}

/***

* class字节流获取

*/

private byte[] getClassByte(String className) throws IOException{

String classRealPath = classPath + File.separatorChar + className.replace('.',File.separatorChar)+".eclass";

byte[] buf = new byte[BUFSIZE];

int c;

ByteArrayOutputStream out = null;

try(InputStream in = new FileInputStream(classRealPath);){

out = new ByteArrayOutputStream();

while ((c = in.read())!=-1){

out.write(EncrypClassFile.decryptAlgorithm(c));

}

}catch (FileNotFoundException ex){

ex.printStackTrace();

}finally {

if(out!=null){

out.close();

}

}

if(out!=null){

return out.toByteArray();

}

return null;

}

}

3.3 测试效果

package classload;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

/**

* @author Lczy-Huang

* @classname MyClassLoaderTest

* @desc 测试类加载

* @date 2020-05-24 20:59

**/

public class MyClassLoaderTest {

public static void main(String []args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {

//自定义类加载器的加载路径

MyClassLoader myClassLoader=new MyClassLoader("C:\\Users\\Lczy-Huang\\Desktop");

//包名+类名

Class c=myClassLoader.loadClass("classload.MyClassLoaderTestClass");

if(c!=null){

Object obj=c.newInstance();

Method method=c.getMethod("test", null);

method.invoke(obj, null);

System.out.println(c.getClassLoader().toString());

}

}

}

运行结果:

This is success

classload.MyClassLoader@12bb4df8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值