类加载器---黑马程序员

来源:互联网 发布:优酷网软件下载 编辑:程序博客网 时间:2024/04/17 01:19
类加载器:将class文件加载到内存,进行处理,就是字节码
jvm有多个类加载器,系统默认三个主要类加载器,每个类辅助加载特定未知的 类
BootStrap,ExtClassLoader,AppClassLoader


类加载器也是java类,因为其他是java类的类加载器本身也要被雷加载器加载,显
然必须有第一个类加载器不是java类,这正是BootStrap
Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,
在实例化每个类装载器对象时候,需要为其指定一个父级类装载器对象时,
需要为其指定一个父级类装载器对象或者默认采用系统类装载器为其父级类加载


2.每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他
的类装载器去加载类,这就是类加载器的委托模式。类装载器一级级委托到BootStra
p类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类
装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的
装载,那就应报告ClassNotFoundException异常。


当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。 
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。
当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,
不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下
的itcast.jar包中后,运行结果为ExtClassLoader的原因。


3.编写自己的类加载器:
1).自定义的类加载器必须继承ClassLoader
2).loadClass方法与findClass方法
3).defineClass方法


4.例程
import java.io.*;import java.lang.reflect.*;public class MyClassLoader extends ClassLoader{private String path = null;public MyClassLoader(String path) throws Exception//检查文件是否存在{File f = new File(path);if(!f.isDirectory()){throw new RuntimeException(path + " is not a directory");}this.path = path;}public Class findClass(String name) //throws Exception //为什么不能抛出{try{File f = new File(path,name.substring(name.lastIndexOf('.')+1) + ".class");FileInputStream fis = new FileInputStream(f);ByteArrayOutputStream bos = new ByteArrayOutputStream();cypher(fis,bos);byte [] buf = bos.toByteArray();fis.close();bos.close();return defineClass(name,buf,0,buf.length);}catch(Exception e){throw new ClassNotFoundException(name + " is not found!");}return null;}public static void cypher(InputStream istream,OutputStream ostream) throws Exception{//下面这段代码可能遇到255的字节,当成byte就成了-1/*byte b = 0;while((b = (byte)istream.read()) != -1){ostream.write(b ^ 0xff);}*/int b = 0;while((b = istream.read()) != -1){ostream.write(((byte)b) ^ 0xff);}}public static void main(String [] args) throws Exception{//下面省略了错误检查if(!args[0].endsWith("class")){ClassLoader loader = new MyClassLoader(args[1]);Class cls = loader.loadClass(args[0]);/*让自定义类继承Date类System.out.println(cls.getClassLoader().getClass().getName());java.util.Date d = (java.util.Date)cls.newInstance();System.out.println(d.toString());*///Method m = cls.getMethod("test",null);//在jdk1.5中报警告,为什么?Method m = cls.getMethod("test");//m.invoke(cls.newInstance(),null);m.invoke(cls.newInstance());//((Test)cls.newInstance()).test();return;}else{ FileInputStream fis = new FileInputStream(args[0]);File f = new File(args[1], new File(args[0]).getName());//不用检查目录最后是否有目录分割符FileOutputStream fos = new FileOutputStream(f);cypher(fis,fos);fis.close();fos.close();}}}//类加载器不能加载这种非public的类/*Exception in thread "main" java.lang.IllegalAccessException: Class MyClassLoader can not access a member of class MyTest with modifiers ""*//*class MyTest{public void test(){System.out.println("hello,www.it315.org");}}*/

0 0