【黑马程序员】java基础加强---------类加载器(classLoader)

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------




一、类加载器定义:

顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。
就是将类的class文件加载进内存的工具,java虚拟机要运行类中的数据,必须先将他的
二进制字节码对象加载进内存,就要要对类加载器。

二、系统中已经存在3个类加载器,他们各自有自己的加载任务(或是范围):


根-加载器(bootstrapClassLoader):它用来加载 Java 的核心库,是用c++编写的一段代码,对于你java是不可见的
扩展类加载器(extClassLoader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录
系统类加载器(AppClassLoader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类


三、java虚拟机要加载一个类时,到底由谁去加载呢?


1、首先当前线程的类加载器去加载线程中的第一个类
2、如果类A引用了类B ,java虚拟机会使用加载A的加载器去加载B
3、还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类

类加载器的委托机制:

1、每个类的字节码成功加载进内存,至始至终是由加载器中的一个为其加载的、
如果内存中已经存在加载过的字节码,避免重复加载,直接调用即可

2、比如说,当一个类A 为发起者,需要AppClassLoader加载,-------->但是它会委托它福加载器:ExtClassLoader----->委托给父类加载器:BootStrap

     再从BootStrap开始往下查找自己负责的范围是否有.class文件,有就加载成功,没有就继续往下,直到发起者

public class Test2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ClassLoader loader=Test2.class.getClassLoader();
		
			System.out.println("本类的加载器:"+loader.getClass().getName());
					
			loader=loader.getParent();
	
		System.out.println("父类加载器:"+loader.getClass().getName());
		loader=loader.getParent();
		//根加载器的getName()为null
		System.out.println("根--加载器:"+loader);
	}

}

打印结果:

本类的加载器:sun.misc.Launcher$AppClassLoader
父类加载器:sun.misc.Launcher$ExtClassLoader
根--加载器:null

四、自定义类加载器


1、自定义类加载器必须继承ClassLoader抽象类,成为类加载器中的体系中,类加载的方式可以按照委托方式进行

2、如果上面的类加载器没有加载成功,本类中只要覆盖findClass()方法,就可以用自己的类加载器进行加载

     这种方式:应用了模板方法设计模式。

五、模拟自定义类加载器用于加载Data类

	import java.util.Date;  
	//定义一个测试类,继承Date,便于使用时加载  
	public class ClassLoaderAttachment extends Date{  
	    //复写toString方法  
	    public String toString(){  
	        return "Hello World!";  
	    }  
	}  
	  
	import java.io.ByteArrayOutputStream;  
	import java.io.FileInputStream;  
	import java.io.FileOutputStream;  
	import java.io.InputStream;  
	import java.io.OutputStream;  
	 //自定义类加载器,模拟类加载器使用自身加载器的过程 
	public class MyClassLoader extends ClassLoader{  
	  
	    public static void main(String[] args) throws Exception {  
	        String srcPath=args[0];//文件源  
	        String destDir=args[1];//文件目的  
	        InputStream ips=new FileInputStream(srcPath);  
	        String destFileName=srcPath.substring(srcPath.lastIndexOf("\\")+1);  
	        String destFilePath=destDir+"\\"+destFileName;  
	        OutputStream ops=new FileOutputStream(destFilePath);  
	        cypher(ips,ops);//加密class字节码  
	        ips.close();  
	        ops.close();  
	    }  
	    //加密方法  
	    private static void cypher(InputStream ips,OutputStream ops) throws Exception{  
	        int b=-1;  
	        while((b=ips.read())!=-1){  
	            ops.write(b^0xff);  
	        }  
	    }  
	  
	    @Override  
	    //覆盖ClassLoader的findClass方法  
	    protected Class<?> findClass(String name) throws ClassNotFoundException {  
	        name=name.substring(name.lastIndexOf(".")+1);  
	        String classFileName=classDir+"\\"+name+".class";//获取class文件名  
	        InputStream ips=null;  
	        try {  
	            ips=new FileInputStream(classFileName);  
	            ByteArrayOutputStream bos=new ByteArrayOutputStream();//定义字节数组流  
	            cypher(ips,bos);//解密  
	            ips.close();  
	            byte[] buf=bos.toByteArray();//取出字节数组流中的数据  
	            return defineClass(null, buf,0,buf.length);//加载进内存  
	              
	        } catch (Exception e) {  
	            // TODO: handle exception  
	            e.printStackTrace();  
	        }  
	        return null;  
	        //return super.findClass(name);  
	    }  
	      
	    private String classDir;  
	    public MyClassLoader(){}  
	    //带参数的构造函数  
	    public MyClassLoader(String classDir){  
	        this.classDir=classDir;  
	    }  
	  
	}  
	  
	import java.util.Date;  
	  
	public class ClassLoaderDemo {  
	  
	    public static void main(String[] args) throws Exception {  
	        //将用自定义的类加载器加载.class文件  
	        Class clazz=new MyClassLoader("itheimalib").loadClass("cn.itheima.demo.ClassLoaderAttachment");  
	        Date d1 =  (Date)clazz.newInstance();//获取Class类的实例对象  
	        System.out.println(d1);  
	    }  
	} 


---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值