类加载器就是加载类的工具 可以有多个类加载器,JVM默认三个类加载器,Bootstrap,ExtClassLoader,AppClassLoader,它们三个继承关系是:Bootstrap是ExtClassLoader的父类,ExtClassLoader是AppClassLoader的父类。
有一个不是java类加载器,bootStrap(比如System就是它加载的),他是内核,c++写的。其他类加载器也都是java类
它们启动的目录分别如下:
bootstrap---jre/lib/rt.jar
extclassloader---jar/lib/ext/*.jar
appclassloader---classpath制定的所有jar或目录
myclassloader---自己制定的特殊目录
那实际应用中用哪个类加载呢 ? 首先是当前线程的类加载器加载线程中的第一个类。先委托父类,父类再委托给父类,如果找不到在一级一级的往下返回,如果父类们都加载不到就用当前类加载。如果当前类加载不了就报错,不会往下找。
下面就编写一个自己的类,编写自己的类加载器,必须继承一个抽象类ClassLoader,它有一个方法loadclass是找父类,findclass是自己做,所以覆盖findclass即可。
步骤:
1.编写一个对文件内容进行简单加密的程序。
2.编写了一个自己的类装载器,可实现对加密过的类进行装载和解密。
3.编写一个程序用类加载器加载类。
package cn.itcast.day1;
import java.util.Date;
public class ClassLoaderAttachment extends Date {
public String toString()
{
return "hello,world";
}
}
package cn.itcast.day1;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MyClassLoader extends ClassLoader{
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String srcPath=args[0];
String destDir=args[1];
FileInputStream fis=new FileInputStream(srcPath);
String destFileName=srcPath.substring(srcPath.lastIndexOf('\\')+1);
String destPath=destDir+"\\"+destFileName;
FileOutputStream fos=new FileOutputStream(destPath);
cypher(fis,fos);
fis.close();
fos.close();
}
private static void cypher(InputStream ips,OutputStream ops) throws IOException{
int b=-1;
while((b=ips.read())!=-1){
ops.write(b^0xff);
}
}
private String classDir;
@Override
protected java.lang.Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName=classDir+"\\"+name+".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis, bos);
fis.close();
byte[] bytes = bos.toByteArray();
return defineClass(bytes, 0, bytes.length);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
//return super.findClass(name);
return null;
};
public MyClassLoader(){
}
public MyClassLoader(String classDir){
this.classDir=classDir;
}
}
package cn.itcast.day1;
import java.util.Date;
public class ClassLoaderTest {
/**
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());
System.out.println(System.class.getClassLoader());
ClassLoader loader=ClassLoaderTest.class.getClassLoader();
while(loader!=null){
System.out.println(loader.getClass().getName());
loader=loader.getParent();
}
System.out.println(loader);
//System.out.println(new ClassLoaderAttachment().toString());
Class clazz=new MyClassLoader("itcastlib").loadClass("ClassLoaderAttachment");
Date d1=(Date)clazz.newInstance();
System.out.println(d1);
}
}