java类加载器学习总结:
1.定义:类加载器就是加载类的工具,当然除了加载类外,类加载器还可以用来去加载一些属性文件和配置文件,但是和一般的用文件方式读取属性文件和配置文件不同,用类加载器加载的文件感知不到文件的变化,当我们的属性文件或配置文件发生改变并需要重新加载的时候,因为类加载器发现内存中已经有需要的属性文件或配置文件时,它就不会再重新到硬盘去加载已经被修改过的属性或资源文件,当我们在用类加载器加载资源文件时要注意这一点。当需要用到一个类的时候,java虚拟机首先将类的字节码加载进内存,他是通过类加载器把需要用到的类加载进内存的
2.java虚拟机中可以安装多个类加载器,系统默认主要有三个类加载器,BootStrap,ExtClassLoader,AppClassLoader,每个加载器负责加载特定的类。
3.类加载器也是java类,因为类加载器本身也要被类加载器加载,所以必须有一个不是java类的类加载器,这个类加载器是BootStrap,它由C语言编写,是嵌套在java虚拟机内核中的随java虚拟机一起启动。
4.java虚拟机中的所有类加载器采用具有父子关系的树形结构进行组织,在实例化每个类加载器对象是需要为其指定父类加载器或采用默认的加载器作为其父类。
5.类加载器的委托机制:
当一个类加载器去加载一个类时,他会先委托他的父类去加载这个类,如果父类无法加载这个类,子类才会自己去加载这个类,类加载器的委托机制,意在防止一个类被多个类加载器加载,当子类也无法加载这个类时会抛ClassNotFoundException异常,即使子类下面还有子类,他也不会委托子类去加载,因为他可能有多个子类,他不知道到底该委托哪个子类去加载
6.系统默认的三个加载器的加载路径:
BootStrap:这个加载器主要加载JRE/lib/rt.java.这个jar包里的类都是系统核心的类。
ExtClassLoader:这个类加载器主要加载JRE/lib/ext/文件夹下面的类,这些类是方便我们开发提供的扩展类。
AppClassLoader:这个类加载器主要加载CLASSPATH指定的目录下面的类,这些类主要是我们自己编写的类。
7.创建用户自定义类加载器:
创建用户自定义类加载器必须继承ClassLoader类,并重写里面的findClass()函数;示例如下:/** * 创建自定义类加载器,通过继承ClassLoader类并重写其findClass方法,其中 * findClass方法返回的是Class对象,我们给我们的类进行加密,并在这个方法中 * 对被加密的类进行解密。 * */ public class myClassLoad extends ClassLoader{ @Override protected Class findClass(String nane){ try{ InputStream is = new FileInputStream(name+".class"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bytedata=0; while( (bytedata = is.read())!=-1){ baos.write(bytedata); } return defineClass(name,baos.toByteArray,0,baos.toByteArray.lenth); }catch(Exception){ e.printStackTrace(); } } }
当用户不想让自己的类加载器去委托父类加载类时,只需要重写loadClass()函数即可;示例如下:
/** * 自定义类加载器,不通过父类加载类:ClassLoader的LoaderClass * 方法是先委派其父加载器加载类当父加载器无法加载时自己才加载, * 我们通过重写这个方法使其不再委派父类去加载类,即直接调用子类的 * findClass方法,这样即使父加载器能加载类或该类已在内存中时仍然去 * 加载这个类,这样可能导致一个类在内存中存在多个副本,不推荐使用 */ public class myClassLoad extends ClassLoader{ @Override protected Class findClass(String name){ try{ InputStream is = new FileInputStream(name+".class");//加载类的字节码文件 ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bytedata=0; while((bytedata=is.read())!=-1){ baos.write(bytedata); } return defineClass(name,baos.toByteArray,0,baos.toByteArray.lenth);//将类的字节码文件转化成类对象 }catch{ e.printStackTrace(); } } @Override Class loadClass(String name){ findClass(name);//这里直接调用子类的findClass函数,就不会委托父类的类加载器去加载了 } }
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
详细请查看:www.itheima.com