由于Java文件编译后生成固定格式的字节码文件, 所以class文件很容易被反编译。
那如何保护自己的字节码文件呢?那就得使用文件加密和自定义ClassLoader了。
下面是我写的一个Demo
1. 老规矩, HelloWorld(^_^)。
public class HelloWorld {
private static String GREETING = "Hello World";
static{
System.out.println("i am loaded");
}
public static void main(String[] args){
System.out.println(GREETING);
}
}
HelloWorld里面就main 函数和一个静态加载块,这个静态加载块主要用于测试自定义ClassLoader的。
2. 生成class文件
编译HelloWorld.java 之后, 会生成HelloWorld.class文件
上面是HelloWorld的class文件,magic 字段值为Cafe Babe
3. 加密class文件
加密方式可以用3次DES加密,在Demo里面,我只做了最最简单的加密
public static byte[] encrypt(byte[] content){
byte[] result = new byte[content.length];
for(int i=0; i<content.length; i++){
result[i] = (byte)((int)content[i] + 1);
}
return result;
}
读取指定的class文件之后,字节 + 1,然后保存加密后的文件。
我这里指定的后缀名为javass。
加密完之后,请删除.class文件
从magic字段可以看出来,已经加密成功了
4. 使用自定义ClassLoader加载字节码文件
java可以手动指定ClassLoader, 因此使我们加载加密的字节码成为了可能。
1. 自定义ClassLoader.
public class MyClassLoader extends ClassLoader
2. 重写findClass方法
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] value = 读取HelloWorld.javass文件(Demo中使用文件路径直接读取)
//解密文件。 解密方法是每个字节 - 1
value = decode(value);
//返回加载的Class对象
Class clazz = defineClass(name, value, 0, value.length);
return clazz;
}
5. main 函数测试是否加载成功
public static void main(String[] args){
MyClassLoader classLoader = new MyClassLoader(文件路径);
Class clazz = classLoader.findClass("HelloWorld");
clazz.newInstance();
}
如果控制台输出- i am loaded.说明你的class文件已经成功加解密了。