场景:项目需要部署在客户的服务器,但是又不想暴露源代码。
方案步骤:
- 使用idea编号好代码后,通过自动编译成class文件,即可获取到核心的class文件;
- 使用加密工具类,读取核心class文件,对class文件进行加密处理,如示例在字节码的尾部加入java字节码;
- 自定义类加载器MyClassLoader集成自ClassLoader, 在重载findClass方法中通过io读取字节码文件,判断尾部后去掉java字节码;
- 项目启动后,调用MyClassLoader完成对加密模块的加载即可。
import java.io.*;
/**
* @Description: 自定义类加载器实现java字节码的加解密
*/
public class MyClassLoader extends ClassLoader{
private String key = "java";
private String codePath;
public MyClassLoader(ClassLoader parent, String codePath) {
super(parent); this.codePath = codePath;
}
public MyClassLoader(String codePath) { this.codePath = codePath; }
/**
* 字节码加密
* @param name
* @return
* @throws ClassNotFoundException
*/
public void writeKey(String name){
BufferedInputStream bis = null;
ByteArrayOutputStream baos = null;
try {
//1.字节码路径
String fileName = codePath + name + ".class";
//2.获取输入流
bis = new BufferedInputStream(new FileInputStream(fileName));
//3.获取输出流
baos = new ByteArrayOutputStream();
//4.io读写
int len;
byte[] data = new byte[1024];
while ((len = bis.read(data)) != -1) {
baos.write(data, 0, len);
}
baos.write(key.getBytes(),0,key.length());
baos.writeTo(new FileOutputStream(fileName));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
protected Class<?> findClass(String name) {
BufferedInputStream bis = null;
ByteArrayOutputStream baos = null;
try {
//1.字节码路径
String fileName = codePath + name + ".class";
//2.获取输入流
bis = new BufferedInputStream(new FileInputStream(fileName));
//3.获取输出流
baos = new ByteArrayOutputStream();
//4.io读写
int len;
byte[] data = new byte[1024];
while ((len = bis.read(data)) != -1) {
if( len < 1024 ){
//快结束了, 取消加密串
baos.write(data, 0, len - key.getBytes().length);
}else{
baos.write(data, 0, len);
}
}
//5.获取内存中字节数组
byte[] byteCode = baos.toByteArray();
//6.调用defineClass 将字节数组转成Class对象
Class<?> defineClass = defineClass(null, byteCode, 0, byteCode.length);
return defineClass;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public static void main(String[] args) {
MyClassLoader classLoader = new MyClassLoader("f:/");
//classLoader.writeKey("TestMain2");
try {
Class<?> clazz = classLoader.loadClass("TestMain");
System.out.println("我是由"+clazz.getClassLoader().getClass().getName()+"类加载器加载 的");
System.out.println( clazz.newInstance() );
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
本文暂时没有评论,来添加一个吧(●'◡'●)