JVM加载类的过程
http://www.51testing.com/?uid-225738-action-viewspace-itemid-223520
昨天,看一个build Standalone中databrusher的一个脚本,发现一个Java类似乎没有在classpath中,好像也可一直运行了。很疑惑,问了对应的开发同学,然后自己好好看了下它的代码,才知道了原理。
命令是:$JAVA_HOME/bin/java $JAVA_OPTS com.alibaba.standalone.AppStartor com.alibaba.intl.standalone.databrusher.Startor "$main_class" "$signal_file" "$recivers"
原理是:Java根据classpath找到,com.alibaba.standalone.AppStartor这个class,运行这个class,会启动一个classloader来加载com.alibaba.intl.standalone.databrusher.Startor(在里面会指定到WORLDS-INF目录下加载类),然后com.alibaba.intl.standalone.databrusher.Startor会启动对应的"$main_class".
然后,花了挺多时间好好看了一下Java的classloader,了解一下其中的原理和看了下代码。下面也简单总结一下吧。
java虚拟机是由sun.misc.Launcher来初始化的,也就是java(或java.exe)这个程序来做的.虚拟机按以下顺序搜索并装载所有需要的类:
java -classpath/-Djava.class.path或$CLASSPATH变量所指的目录下的类与jar包装入工作.(这里需要说明的是,如果$CLASSPATH为空,jdk会默认将被运行的Java类的当前路径作为一个默认的$CLASSPATH,一但设置了$CLASSPATH变量,则会到$CLASSPATH对应的路径下去寻找相应的类,找不到就会报错。这个结论,我已经经过测试,并且看了下类加载器中源代码)d. User Custom ClassLoader/用户自定义类加载类(java.lang.ClassLoader的子类)在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性.(暂时理解为需要的时候才加载类,不像基础功能的类是全部预加载了)
为了有更多的了解,写了个简单的Java程序对前面三种classloader能加载类的路径及其parent类进行了测试。代码如下:
import java.net.URL;import java.net.URLClassLoader; /** * @className: IClassLoader * @description: 测试三种classloader加载类的路径,及其parent * @author: 笑遍世界 * @createTime: 2010-11-17 下午07:33:40 */public class IClassLoader { public static void main(String[] args) {// 测试bootstrap classloader 的类加载路径 URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs(); for (int i = 0; i < urls.length; i++) { System.out.println(urls[i].toExternalForm()); } // 测试extension classloader 的类加载路径,先打印一个路径,再打印出其parent,然后再打印出类加载路径中的所有jar包 System.out.println("-------------------------------------"); System.out.println(System.getProperty("java.ext.dirs")); ClassLoader extensionClassloader=ClassLoader.getSystemClassLoader().getParent(); System.out.println("the parent of extension classloader : "+extensionClassloader.getParent()); System.out.println("extension classloader can use thess jars:"); URL[] extURLs = ((URLClassLoader)ClassLoader.getSystemClassLoader().getParent()).getURLs(); for (int i = 0; i < extURLs.length; i++) { System.out.println(extURLs[i]); } // 测试system classloader 的类加载路径,其实也就时classpath的路径,并打印出它的parent System.out.println("-------------------------------------"); System.out.println(System.getProperty("java.class.path")); System.out.println(ClassLoader.getSystemResource("")); ClassLoader systemClassloader=ClassLoader.getSystemClassLoader(); System.out.println("the parent of system classloader : "+systemClassloader.getParent()); }} 本机(linux+jdk1.5)运行结果如下:file:/usr/ali/java/jre/lib/rt.jarfile:/usr/ali/java/jre/lib/i18n.jarfile:/usr/ali/java/jre/lib/sunrsasign.jarfile:/usr/ali/java/jre/lib/jsse.jarfile:/usr/ali/java/jre/lib/jce.jarfile:/usr/ali/java/jre/lib/charsets.jarfile:/usr/ali/java/jre/classes-------------------------------------/usr/ali/java/jre/lib/extthe parent of extension classloader : nullextension classloader can use thess jars:file:/usr/ali/java/jre/lib/ext/emma.jarfile:/usr/ali/java/jre/lib/ext/localedata.jarfile:/usr/ali/java/jre/lib/ext/dnsns.jarfile:/usr/ali/java/jre/lib/ext/sunpkcs11.jarfile:/usr/ali/java/jre/lib/ext/sunjce_provider.jar-------------------------------------.:/usr/ali/java/lib/dt.jar:/usr/ali/java/lib/tools.jarfile:/home/master/workspace/2010_11/bin/the parent of system classloader : sun.misc.Launcher$ExtClassLoader@1a5ab41
//ps:当前路径.即是/home/master/workspace/2010_11/bin/
关于Java的classloader其原理还是需要好好理解才能清楚的,仅通过一天的了解,记录为上面那么多吧。更多详细信息,可以参考如下资料:
http://snandy.javaeye.com/blog/307083http://haofenglemon.javaeye.com/blog/426382
http://blog.csdn.net/zdwzzu2006/archive/2008/04/05/2253982.aspx
http://wuquanyin1011.javaeye.com/blog/703842
http://hi.baidu.com/yangzhibin_bai/blog/item/78846cce1cb86b0992457ead.html
http://www.blogjava.net/clraychen/archive/2008/02/20/180868.html