前言:本博客内容由张孝祥Java高新技术整理而来
package com.dao.chu.myloader; import java.util.Date; @SuppressWarnings("serial") public class ClassLoaderAttach extends Date{ @Override public String toString() { return "this is ClassLoaderAttach"; } }
package com.dao.chu.myloader; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class MyClassLoader { public static void main(String[] args) throws IOException { String srcPath = args[0]; String destDir = args[1]; String destFileName = srcPath.substring(srcPath.lastIndexOf("\\") + 1); String destFilePath = destDir + "\\" + destFileName; FileInputStream fin = new FileInputStream(srcPath); FileOutputStream fout = new FileOutputStream(destFilePath); cypher(fin,fout); fin.close(); fout.close(); } /** * <p>Title: cypher</p> * <p>Description:加密, 将原来的1改为0,0改为1</p> * @param in * @param out * @throws IOException */ public static void cypher(InputStream in ,OutputStream out) throws IOException{ int b=0; while ((b=in.read())!=-1) { out.write(b ^ 0xff); } } }
package com.dao.chu.myloader; public class MyClassLoaderTest { public static void main(String[] args) { ClassLoaderAttach classLoaderAttach = new ClassLoaderAttach(); System.out.println(classLoaderAttach.toString()); } }
运行 MyClassLoader,输入ClassLoaderAttach.class的路径和要生成至的路径。
运行成功后可看到有加密后的class文件生成
执行MyClassLoaderTest,可看到正常输出
我们将加密的class文件与原来没加密过的class文件进行替换
再次执行MyClassLoaderTest,可看到报错信息。说明加密成功,用原来的类加载器不能运行,所以我们要用自己的类加载器运行
package com.dao.chu.myloader; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class MyClassLoader extends ClassLoader{ public static void main(String[] args) throws IOException { String srcPath = args[0]; String destDir = args[1]; String destFileName = srcPath.substring(srcPath.lastIndexOf("\\") + 1); String destFilePath = destDir + "\\" + destFileName; FileInputStream fin = new FileInputStream(srcPath); FileOutputStream fout = new FileOutputStream(destFilePath); cypher(fin,fout); fin.close(); fout.close(); } /** * <p>Title: cypher</p> * <p>Description:加密, 将原来的1改为0,0改为1</p> * @param in * @param out * @throws IOException */ public static void cypher(InputStream in ,OutputStream out) throws IOException{ int b=0; while ((b=in.read())!=-1) { out.write(b ^ 0xff); } } private String classDir; public MyClassLoader(){ } public MyClassLoader(String classDir){ this.classDir=classDir; } /** * 覆盖ClassLoader的findClass方法 */ @SuppressWarnings("deprecation") @Override protected Class<?> findClass(String name) throws ClassNotFoundException { String classFileName = classDir + "\\" + name + ".class"; try { FileInputStream fin = new FileInputStream(classFileName); ByteArrayOutputStream baout = new ByteArrayOutputStream(); //解密 cypher(fin,baout); fin.close(); //转为字节数组 byte[] byteArray = baout.toByteArray(); return defineClass(byteArray, 0, byteArray.length); } catch (Exception e) { } return null; } }
package com.dao.chu.myloader; import java.util.Date; public class MyClassLoaderTest { @SuppressWarnings("rawtypes") public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { // ClassLoaderAttach classLoaderAttach = new ClassLoaderAttach(); // System.out.println(classLoaderAttach.toString()); Class c = new MyClassLoader("myloaderlib").loadClass("ClassLoaderAttach"); Date d = (Date)c.newInstance(); System.out.println(d); } }
测试前我们需将原来生成的ClassLoaderAttach.class删掉,避免父类加载影响结果
正是我们想要的结果