您的位置:首页 > 职场人生

《黑马程序员》 类加载器之加密解密类

2014-03-20 22:35 253 查看
------- android培训java培训、期待与您交流! ----------
package cn.itcast.day2.part320review;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class MyClassLoader2  extends ClassLoader{

/**
*自定义类加载器
*  对指定的类进行加密
*  然后使用自己的类加载器将加密的类进行解密
*
*  我们测试分二步:
*      第一步,测试普通类的时候加密
*         只测试是否可以将一个类进行加密
*           使用参数的方式传参给jvm:E:\javaenhance\javaenhance\bin\cn\itcast\day2\part320review\
*              MyClassAttachment.class itcastlib
*           然后检查指定目录itcastlib目录中是否有加密的文件
*           创建测试对象调用toString方法并且打印。看效果
*
*           然后进入下一步测试,就是删除掉classPath下的class, 把加密之后的class文件放入,测试效果
*           出现类型格式错误,这就是说明我们加密成功了
*      第二步,我们将加密的class发给别人,别人放到claspath下面是不可能直接使用的。
*          我们要做的就是自定义一个类加载器,使用我们自己的类加载器来将加密的class进行解密
*          然后创建一个对象,进行测试。
*            创建一个自定义的class加载器。它默认指定的父级就是AppClassLoader,因为我们一般都是委托给
*            父级类加载器进行操作的,它们调用的是Class.loadClass方法,然后当父类返回之后,再调用
*            findClass方法。我们想让自己来调用,想避过类加载器的委托机制。我们直接在自己的类加载器中
*            的findClass中进行返回即可
*
*              为了简便操作,我们就使用当前的类来做自定义的类加载器了。
*                需要注意的是,我们的自定义类加载器写完之后一定要运行一下,要不然可能和我们预期的测试
*                结果相反,这也是今天郁闷了一天。到最后解决的问题。
*
*                第二步测试的时候要把第一步测试的itcastlib目录中的文件给删除掉。让它重新生成
*
*                 测试,我们调用我们的自定义的类加载器
*/
public static void main(String[] args) throws Exception {
//我们获取用户传入要加密的文件的路径
String srcPath=args[0];
//获取用户存放加密之后文件的目录
String destDir=args[1];
FileInputStream fis=new FileInputStream(srcPath);
//从文件路径中得到文件名
//在()中要使用''不要使用""
//String.subString是包含头不包含尾的
String destFileName=srcPath.substring(srcPath.lastIndexOf('\\')+1);
//使用目标目录和文件名组拼文件的路径
String destFilePath=destDir+"\\"+destFileName;
//定义文件输出流
FileOutputStream fos=new FileOutputStream(destFilePath);
//调用加解密的方法
crypher(fis, fos);
fis.close();
fos.close();
}

//加密的方法:
//我们对数据进行^运算,1变0加密,0变1解密
public  static void crypher(InputStream ism,OutputStream osm) throws Exception{
//定义变量记录住读取的数据的个数
int b=-1;
while((b=ism.read())!=-1){ //如果没有读取到文件的末尾
osm.write(b^0xff);  //将读取的数据写入,并且让它^一个字节。
}
}

private String classDir;

MyClassLoader2(){
}

MyClassLoader2(String classDir){
this.classDir=classDir;
}

//加载类,需要传入加载的类名,我们通过构造方法来实现,让用户在创建本类对象的时候
//传递需要加载的类的名称,然后我们根据类的名称来找到与之对应的字节码
@Override
protected Class<?> findClass(String name) {
try {
//我们根据用户传入的要加载类的目录和类名来组拼.class文件
String classFileName = classDir + "\\" + name.substring(name.lastIndexOf('.')+1) + ".class";
//使用文件输入流来加载类文件
FileInputStream fis = new FileInputStream(classFileName);
//字节数组输出流,将结果输出到字节数组中
//使用这个是因为我们要使用define方法将字节数组成定义成Clss对象然后返回
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//调用解密的方法
crypher(fis, baos);
fis.close();
System.out.println("自定义的类完成的加载");
byte[] bytes=baos.toByteArray();
return defineClass(bytes, 0, bytes.length);  //把字节数组中的从0开始到数组的末尾,都转换成Class并且返回
} catch (Exception e) {
// TODO: handle exception
}
return null;
}

}


package cn.itcast.day2.part320review;

import java.util.Date;

public class MyClassAttachment extends Date {
@Override
public String toString() {
// TODO Auto-generated method stub
return "hello,itcast";
}
}
package cn.itcast.day2.part320review;

import java.util.Date;

public class MyClassLoaderTest {

/**
* 用于测试
*/
public static void main(String[] args) throws Exception{
//获取加载当前类的类加载器
System.out.println(MyClassLoaderTest.class.getClassLoader().getClass().getName());
System.out.println(System.class.getClassLoader());

ClassLoader loader=MyClassLoaderTest.class.getClassLoader();
while(loader!=null){
System.out.println(loader.getClass().getName()); //打印类加载器的名称
loader=loader.getParent();  //获取当前器加载器的父类
}
System.out.println(loader);

//		System.out.println(new MyClassAttachment().toString());

Class clazz=new MyClassLoader2("itcastlib").loadClass("cn.itcast.day2.part320review.MyClassAttachment");
//我们在类中不能使用本类做为类型出现,因为如果出现了,类加载器就会把本类重新给加载进内存
//如果本类是被加密的,那编译就会不通过
//所以我们可以使用父类来实现
Date d1=(Date)clazz.newInstance();
System.out.println(d1);
}

}


测试了一天,终于测试成功了。使用自己的类加载器,对加密后的文件进行解密。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息