Java虚拟机中可以安装多个类加载器,
系统默认三个主要类加载器,每个类负责加载特定位置的类:
BootStrap,
ExtClassLoader,AppClassLoader
类加载器也是Java类,因为其他是java类的类加载器本身也要被类加载器加载,既然这样第一个类加载器又是谁加载的呢?
显然必须有第一个类加载器不是不是java类,这正是BootStrap。
Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载。
体验类加载器
public class ClassLoaderTest
{
public static void main(String[] args) throws Exception
{
System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());
}
}
2 如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
3 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
1当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
2每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异常。
把先前编写的类加入到jdk的rt.jar中,会有怎样的效果呢?不行!!!
编写自己的类加载器
1. 知识讲解
自定义义的类加载器必须继承ClassLoader
loadClass方法与findClass方法
defineClass方法
2. 编程步骤
1. 编写一个对文件内容进行简单加密的程序
2. 编写一个自己的类装载器,可以实现对加密过的类装载和界面
3. 编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类,程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统加载器,然后使用Class.forName
3. 实验步奏
1. 对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如:javaMyClassLoader MyTest.classs F:\itcast
2. 运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppC
lassLaoder: javaMyClassLoader MyTest F:\itcast
3. 用加密后的类文件替换CLASSPATH环境下的类文件,再执行上一步操作就出现问题了,错误说明是AppClassLoader类装载失败
4. 删除CLASSSPATH环境下的类文件,再执行上一步操作就没有问题了
编写对class文件进行加密的工具类
package com.itcast.day2;
import java.io.*;
public class MyClassLoader
{
public staticvoid main(String[] args) throws Exception
{
StringsrcPath=args[0];
StringdestDir=args[1];
StringdestName=srcPath.substring(srcPath.lastIndexOf("\\")+1);//分割得到文件名
StringdestPath=destDir+"\\"+destName;//拼装路径
FileInputStreamfis=new FileInputStream(srcPath);
FileOutputStreamfos=new FileOutputStream(destPath);
cyhelper(fis,fos);
fis.close();
fos.close();
//G:\Programme\Myeclipse_set\workspace_eclipse\hibernate\java_enhance\bin\ClassLoaderAttachment.class
}
//简单加密算法
private staticvoid cyhelper(InputStreamips,OutputStream ops) throwsException
{
intb=-1;
while((b=ips.read())!=-1)
{
ops.write(b^0xff);
}
}
}
import java.util.Date;
public class ClassLoaderAttachmentextends Date
{
@Override
public String toString()
{
return "helloitcast";
}
}
将生成的itcastlib目录下的ClassLoaderAttachment.class 替换掉原来的class文件
package com.itcast.day2;
public class ClassLoaderTest
{
public staticvoid main(String[] args)
{
//打印出hello itcast
System.out.println(new ClassLoaderAttachment().toString());
}
}
编写和测试自己编写的解密类加载器
package com.itcast.day2;
import java.util.Date;
public class ClassLoaderAttachmentextends Date
{
@Override
public String toString()
{
return "helloitcast";
}
}
package com.itcast.day2;
import java.io.*;
public class MyClassLoader extends ClassLoader
{
public staticvoid main(String[] args) throws Exception
{
StringsrcPath=args[0];
StringdestDir=args[1];
StringdestName=srcPath.substring(srcPath.lastIndexOf("\\")+1);
StringdestPath=destDir+"\\"+destName;//拼装路径
FileInputStreamfis=new FileInputStream(srcPath);
FileOutputStreamfos=new FileOutputStream(destPath);
cyhelper(fis,fos);
fis.close();
fos.close();
//G:\Programme\Myeclipse_set\workspace_eclipse\hibernate\java_enhance\bin\ClassLoaderAttachment.class
}
//简单加密算法
private staticvoid cyhelper(InputStreamips,OutputStream ops) throwsException
{
intb=-1;
while((b=ips.read())!=-1)
{
ops.write(b^0xff);//0->1 1->0
}
}
private String classDir;
//覆盖方法
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException
{
String classFileName=classDir+"\\"+name+".class";//找文件
FileInputStream fis=null;
try
{
fis=newFileInputStream(classFileName);
ByteArrayOutputStream bos=new ByteArrayOutputStream();//转成字节数组,方便操作
cyhelper(fis,bos);//解密
fis.close();
byte[]bytes=bos.toByteArray();
return defineClass(bytes,0,bytes.length);
}
catch(Exception e)
{
System.out.println("出现异常");
e.printStackTrace();
}
return super.findClass(name);
}
public MyClassLoader()
{
}
public MyClassLoader(String classDir)
{
this.classDir=classDir;
}
}
package com.itcast.day2;
import java.util.Date;
public class ClassLoaderTest
{
public staticvoid main(String[] args) throws Exception
{
//打印出hello itcast
// System.out.println(new ClassLoaderAttachment().toString());
Class classzz=new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachment");
Date d1=(Date) classzz.newInstance();
System.out.println(d1);
}
}