黑马程序员——类加载器

--------------android培训java培训、学习型技术博客、期待与您交流! --------------

 

1,类加载器及其委托机制的深入分析。

(1)由来:JVM将类的字节码(编译好的class文件)加载到内存中。

      这是一件很重要的事,这件事是由JVM分配给类加载器在做。

(2),分类:JVM可以有多个加载器。系统默认了3个主要的类加载器。 BootStrap(不是java类),ExtClassLoader,AppClassLoader 负责加载特定位置的类。

 (3),特殊:BootStrap。竟然类加载器也是java类,在用到它们的时候。同样,也需要类加载器进行加载。很显然,这个时候就需要一个不是Java类的加载器。需要找到这个鼻祖,充当这个鼻祖的就是:BootStrap。它不是java类。

(4)关系

每个加载器只能加载指定位置的类。也可以自己定义一个加载器,指定加载

的位置。级别关系:BootStrap->ExtClassLoader->AppClassLoader

体现这种关系的方法是:ClassLoader里面的getParent()方法。

5),委托

原理,每个类加载器加载类时,都会委托给它的上级加载器。当所有的祖宗都没法加载这个类的时候,就会回到发起者类加载器。还是加载不了,就会抛出ClassNotFoundException。不会再去找发起者类加载器的儿子,因为没有getChild方法。

好处,可以集中管理。上级加载完后,下级直接哪来用就行了。否则,会加载很多已经加载的类。

面试题:写一个java.lang.System

(6),指定加载器。

首先当前线程的类加载器去加载线程中的第一个类。如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。还可以直接调用ClassLoader对象的.loadClass()方法来用当前的类加载器去加载某个类。

2,自定义类加载器的编写原理分析。

(1)目标:自定义一个类加载器,并指定加载位置。保证该位置中的类都能被自定义类加载器加载。并且这些类的字节码都有进行加密处理。加载过程中进行解密。

(2)设计模式:模版方法设计模式,父类指定处理大纲,子类规定具体内容的设计模式。一般,在父类中声明子类需要重写的抽象方法(findClass),并且父类中存在一个方法(loadClass)调用了这些方法,保证事件的流程来完成一件相对的大事。

 

(3)返回字节码:defineClass

3,编写对class文件进行加密的工具类。

(1),加密方法:

// 定义一个加密方法,对ClassLoaderAttachment进行加密。
	public static void cypher(InputStream in, OutputStream out)
			throws Exception {
		int b = -1;
		while ((b = in.read()) != -1) {
			b = b ^ 0xff;
			out.write(b);
		}
		in.close();
		out.close();
	}

(2),findClass方法:

protected Class<?> findClass(String name) throws ClassNotFoundException {
		String classPath = classDir+"\\"+name.subString(name.lastIndexOf(‘.’)+1)+".class";
		FileInputStream fis = null;
		ByteArrayOutputStream fos = null;
		try {
			 fis = new FileInputStream(classPath);
			 fos = new ByteArrayOutputStream();
			 cypher(fis,fos);
			 byte[] buf = fos.toByteArray();
//			 byte[] buf = new byte[fis.available()];
//			 fis.read(buf);
			 
//			 读取class文件,把读取的字节转换成字节码到内存中。
			 return defineClass(buf, 0, buf.length);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(fis!=null){
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return super.findClass(name);
	}

(3),调用:

Class clazz = new MyClassLoader("classloaderlib").loadClass("classloader.ClassLoaderAttachment");
		ClassLoader loader = clazz.getClassLoader();
		while(loader!=null){
			System.out.println(loader.getClass().getName());
			loader = loader.getParent();
		}
//		ClassLoaderAttachment cla = (ClassLoaderAttachment) clazz.newInstance();
		System.out.println(loader);


--------------android培训java培训、学习型技术博客、期待与您交流! --------------


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值