黑马程序员-类加载器

---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------

类加载器:

Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrapExtClassLoaderAppClassLoader

类加载器也是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是最顶级的,ExtClassLoaderBootStrap的子类,而AppClassLoaderExtClassLoader的子类

测试:

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,再将加密后的ClassLoaderAttachmentclass覆盖原先的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>、期待与您交流! ---------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值