---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------
类加载器:
Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap、ExtClassLoader、AppClassLoader。
类加载器也是java类,因为其他事java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是java类,这正是BootStrap类加载器。
现在我们来测试两个类,看看他们的类加载器分别是什么?
public class ClassLoaderDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(ClassLoaderDemo.class.getClassLoader().getClass()
.getName());
System.out.println(System.class.getClassLoader());
}
}
输出结果:
第二个输出结果为null,说明System的类加载器为BootStrap
其实从上面的图中也可以看出,BootStrap是最顶级的,ExtClassLoader是BootStrap的子类,而AppClassLoader是ExtClassLoader的子类
测试:
ClassLoader loader=ClassLoaderDemo.class.getClassLoader();
while(loader!=null)
{
System.out.println(loader.getClass().getName());
loader=loader.getParent();
}
System.out.println(loader);
输出结果:
既然每个类加载器都是负责制定区域的jar包,那么我们复制上面的ClassLoaderDemo类的jar文件到jre/lib/ext/classloaderdemo.jar,看看会有什么结果
步骤:项目--------(右键)Export-----
如图:
接下来
接下来在运行上面的程序:
System.out.println(ClassLoaderDemo.class.getClassLoader().getClass().getName());
输出结果:sun.misc.Launcher$ExtClassLoader
我们也可以自己定义类加载器,每个类加载器都应该有自己的父类,在构造函数中定义
有一道面试题:能不能自己写个类叫java.lang.System
回答:写了也白写,,为了不让我们写System类,类加载器采用委托机制,这样可以保证父类优先,这样在Bootstrap中就会找见系统的System,然后加载,不会加载我们写的。
有包名的类不能调用无包名的类
编写自己的类加载器:
引入:
定义一个简单的类ClassLoaderAttachment,再定义一个类MyClassLoader对其class文件进行加密,在上面的ClassLoader类中打印ClassLoaderAttachment,再将加密后的ClassLoaderAttachment的class覆盖原先的class ,看看打印结果。
ClassLoaderAttachment类
public class ClassLoaderAttachment {
@Override
public String toString() {
// TODO Auto-generated method stub
return "Hello Kitty";
}
}
MyClassLoader 类
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class MyClassLoader {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String src = args[0];
System.out.println(src);
String desPathtemp = src.substring(0, src.lastIndexOf('\\'));
String desPath = desPathtemp
.substring(0, desPathtemp.lastIndexOf('\\'));
String desName = src.substring(src.lastIndexOf('\\') + 1);
String desDir = args[1] + "\\" + desName;
System.out.println(desPath);
System.out.println(desDir);
InputStream ins = new FileInputStream(src);
OutputStream ous = new FileOutputStream(desDir);
encryption(ins, ous);
}
public static void encryption(InputStream ins, OutputStream ous)
throws Exception {
int re = -1;
while ((re = ins.read()) != -1) {
ous.write(re ^ 0xff);
}
ins.close();
ous.close();
}
}
ClassLoaderTest 类
public class ClassLoaderTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(ClassLoaderAttachment.class.getClassLoader()
.getClass().getName());
}
}
输出结果:
现在我将加密后的ClassLoaderAttachment类的class文件覆盖原先的class文件,观察结果:
这说明虚拟机已经不认识经过加密后的class文件了,此时就需要用我们自定义的类加载器,让MyClassLoaderAttachment继承ClassLoader并覆盖findClass()方法
MyClassLoader类:
增加代码:
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// TODO Auto-generated method stub
try {
System.out.println(name);
InputStream ins=new FileInputStream(name);
ByteArrayOutputStream os=new ByteArrayOutputStream();
encryption(ins,os);
byte[] by=os.toByteArray();
return defineClass(by, 0, by.length);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.findClass(name);
}
ClassLoaderTest 类
public class ClassLoaderTest {
/**
* @param args
*/
private static String className = "E:\\android\\tarneworkspace\\ClassLoaderDemo\\myclasslib\\ClassLoaderAttachment.class";
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
// System.out.println(ClassLoaderAttachment.class.getClassLoader().getClass().getName());
Class clazz = new MyClassLoader().loadClass(className);
System.out.println(clazz.getClassLoader().getClass().getName());
Object d1 = clazz.newInstance();
System.out.println(d1);
}
}
输出结果:
不过运行前需要先将lib下的ClassLoaderAttachment.class删除,只有父类找不见的情况下,才能轮到子类加载器加载
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ---------------------