- 知识讲解
- 自定义的类加载器必须继承ClassLoader
- loadClass方法与findClass方法
- defineClass方法
- 编程步骤
- 编写一个对文件内容进行简单加密的程序。
- 编写一个自己的类加载器,可实现对加密过得类进行加载和解密。
- 编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类。程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName。
- 实验步骤:
- 对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如:java MyClassLoader MyTest.class F:\itcast
- 运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast


package com.itcast.day3;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 1 加载
* 2 加密
* 3 自定义类加载
* @author hp
*
*/
public class MyClassLoader extends ClassLoader{
public static void main(String[] args) throws Exception{
String srcPath=args[0];
String destDir=args[1];
//加载.class,加密.class,写到自定义目录
FileInputStream fis=new FileInputStream(srcPath);
String destPath=destDir+"\\"+srcPath.substring(srcPath.lastIndexOf("\\"));
FileOutputStream fos=new FileOutputStream(destPath);
cyp(fis,fos);
fis.close();
fos.close();
}
/**
* 加密 or 解密
* @param ips
* @param ops
* @throws Exception
*/
private static void cyp(InputStream ips,OutputStream ops)throws Exception{
int b=-1;
while((b=ips.read())!=-1){
ops.write(b^0xff);
}
}
private String fileDir;//.class文件路径
/**
* 自定义类加载
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName=fileDir+"\\"+name+".class";
try {
FileInputStream fis=new FileInputStream(classFileName);
ByteArrayOutputStream bos=new ByteArrayOutputStream();
cyp(fis,bos);
fis.close();
byte[] bytes=bos.toByteArray();
return defineClass(bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}
public MyClassLoader(){
}
public MyClassLoader(String fileDir){
this.fileDir=fileDir;
}
}
package com.itcast.day3;
import java.util.Date;
/**
* 要加载的类
* @author liujl
*继承自Date是因为方便接收newInstance返回值,不然写成ClassLoaderAttachment自己时,编译不通过(加密过)
*/
public class ClassLoaderAttachment extends Date {
@Override
public String toString(){
return "hello itcast";
}
}
package com.itcast.day3;
import java.util.Date;
/**
* 类加载器测试
* @author ljl
*
*/
public class ClassLoaderTest {
public static void main(String[] args)throws Exception {
/**
* 01.逐一编写下列代码,说明放置在不同位置的类确实由不同的类加载器加载的。
*/
//sun.misc.Launcher$AppClassLoader
System.out.println(ClassLoaderTest.class.getClassLoader()
.getClass().getName());
//Exception in thread "main" java.lang.NullPointerException
//报空指针,说明 ClassLoaderTest和System 这两个类实际存放位置不同,也确实不是同一个类加载器加载的
//System是由BootStrap加载的
// System.out.println(System.class.getClassLoader().getClass().getName());
//null ,类加载器为null说明,不存在类加载器的java类实例,那么System一定是由jvm的核心加载器BootStrap负责加载
System.out.println(System.class.getClassLoader());
/**
* 02.查看类加载器的层次结构关系
*/
System.out.println("\n*******查看类加载器的层次结构关系");
ClassLoader loader=ClassLoaderTest.class.getClassLoader();
while(loader!=null){
System.out.println(loader.getClass().getName());
loader=loader.getParent();
}
System.out.println(loader);
/**运行结果
* sun.misc.Launcher$AppClassLoader---孙子
sun.misc.Launcher$ExtClassLoader---爸爸
null--爷爷--BootStrap
*/
/**
* 03.使用自己定义的类加载器加载特定目录下的类
*/
//System.out.println(new ClassLoaderAttachment().toString());
Class clazz=new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachment");
Date d1=(Date)clazz.newInstance();
System.out.println(d1);
}
}
开始做,坚持做,重复做