星期四, 八月 10, 2006

[修]关于Java 类的载入

构造类的时候可以动态地载入内存,这样可以从一定程度上提高效率,所有类的载入都需要有ClassLoader 。

显式的动态载入类有两种方法:一种是Class.forName() ,一种是ClassLoader.loadClass() ,它们得到的都是Class 对象,也就是相应类的元数据,然后调用newInstance() 方法就可以构造这个类的对象了。这两种方法的原理都是用一个现有的ClassLoader来载入类。我们可以直接使用默认的ClassLoader 来载入类,也可以实现自己的ClassLoader(URLClassLoader 就是一个例子) 来载入。

对于默认的ClassLoader 载入类:JVM 有三个ClassLoader,分别是Bootstrap Loader(这个装载器是C++ 写的,直接与JVM 打交道),ExtClassLoader,AppClassLoader。默认情况下先请求AppClassLoader 来搜索class 文件,AppClassLoader 再向其parent 类ExtClassClassLoader 请求,ExtClassClassLoader再请求其parent“类”Bootstrap Loader 搜索。如果父装载器在其搜索路径里找不到class文件就返回再由子装载器搜索,如果一直到AppClassLoader 找不到就会抛出NoClassDefFoundError。这就是ClassLoader Hierarchy,简而言之就是所有转载请求一直发送到Bootstrap Loader,然后找不到才由子装载器装载——这是一个安全的类载入机制!!确保Java 核心类的载入,而不会被不法的类“冒名顶替”!!

下面介绍3个转载器的搜索路径:
Bootstrap Loader:System.getProperty("sun.boot.class.path") 得到,默认是jre/classes。修改的方法是执行程序的时候使用java -Dsun.boot.class.path=yourPath XXX
ExtClassLoader:System.getProperty("java.ext.dirs") 得到,默认是jre/lib/ext。修改的方法是执行程序的时候使用java -Djava.ext.dirs=yourPath XXX
AppClassLoader:System.getProperty("java.class.path") 得到,默认就是环境变量中的CLASSPATH。修改方法一个是修改环境变量,一个执行程序的时候使用java –classpath yourPath XXX

了解了这些以后我们就可以对类的装载有一定了解,以后放置第三方jar包的时候就能清楚放在什么目录最合适。还有值得一提的是,JDBC驱动和JNDI的类装载涉及ContexClassLoader,它跟上面的原理是不一样的。

没有评论: