-------------
类加载器:
简要介绍什么是类加载器和类加载器的作用:
Ø
Ø
Ø
类加载器之间的父子关系和管辖范围图
类加载器的委托机制
当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
1.首先当前线程的类加载器去加载线程中的第一个类。
2.如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
3.还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的itcast.jar包中后,运行结果为ExtClassLoader的原因。
编写自己的类加载器
知识讲解:
1,自定义的类加载器的必须继承ClassLoader
2,loadClass方法与findClass方法
3,defineClass方法
编程步骤:
1,编写一个对文件内容进行简单加密的程序。
2,编写了一个自己的类装载器,可实现对加密过的类进行装载和解密。
3,编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类。程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName。
实验步骤:
1,对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如: java MyClassLoader MyTest.class F:\itcast
2,运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast
3,用加密后的类文件替换CLASSPATH环境下的类文件,再执行上一步操作就出问题了,错误说明是AppClassLoader类装载器装载失败。
4,删除CLASSPATH环境下的类文件,再执行上一步操作就没问题了。
注意:有包名的类不能调用无包名的类。父类不能加载不带包名的。
代码示例:
//需要加密的类
public class EncryptClass extends SupterEncryptClass{
public EncryptClass(){}
public String toString() {
// TODO Auto-generated method stub
return "我成功了,哈哈!";
}
}
//加密操作
public class Encrtpt {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
String srcPath = args[0];//执行java命令时传入
String destDir = args[1];
FileInputStream fis =new FileInputStream(srcPath);
String destPath =destDir +"\\"+ srcPath.substring(srcPath.lastIndexOf('\\')+1);
FileOutputStream fos = new FileOutputStream(destPath);
System.out.println(destPath);
cypher(fis, fos);
fis.close();
fos.close();
}
public static void cypher(InputStream ips,OutputStream ops)throws Exception//加密算法
{
int b = -1;
while((b=ips.read())!=-1)
{
ops.write(b^0xff);
}
}
}
//定义自己的加载器
public class MyLoaderClass extends ClassLoader {
private String classDir;
public MyLoaderClass(){}
public MyLoaderClass(String classDir)
{
this.classDir = classDir;
}
public void cypher(InputStream ips,OutputStream ops)throws Exception
{
int b = -1;
while((b=ips.read())!=-1)
{
ops.write(b^0xff);
}
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// TODO Auto-generated method stub
String classFileName = classDir + "\\" + name.substring(name.lastIndexOf('.')+1)+".class";
try
{
FileInputStream fs = new FileInputStream(classFileName);
ByteArrayOutputStream bo = new ByteArrayOutputStream();
cypher(fs,bo);//解密
byte[] by = bo.toByteArray();
return defineClass(null,by,0,by.length);//返回解密后的Class文件
}
catch(Exception e)
{
e.printStackTrace();
}
return super.findClass(name);
}
}
//主函数
public class ClassLoaderTest {
public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
MyLoaderClass ml = new MyLoaderClass("itcastlib");
Class<?> en = ml.loadClass("com.itcast.EncryptClass");
SupterEncryptClass s = (SupterEncryptClass)en.newInstance();
System.out.println(s.toString());
}
}