昨天,看一个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)这个程序来做的.虚拟机按以下顺序搜索并装载所有需要的类:
1,引导类:组成java平台的类,包含rt.jar和i18n.jar等基础jar包中的类.
2,扩展类:使用java扩展机制的类,都是位于扩展目录($JAVA_HOME/jre/lib/ext)中的.jar档案包.
3,用户类:开发者定义的类或者没有使用java扩展机制的第三方产品.你必须在命令行中使用-classpath选项或者使用CLASSPATH环境变量来确定这些类的位,或者自己写ClassLoader加载。
Java的class loader的大致情况如下图所示:
http://renyongjie668.blog.163.com/prevPhDownload.do?host=renyongjie668&albumId=197449439&photoId=6568564371
bootstrap classloader -->extension classloader-->system classloader
虚拟机一启动,会先做一些初始化的动作。一旦初始化动作完成之后,就会产生第一个类加载器,即所谓的Bootstrap ClassLoader,Bootstrap ClassLoader 是由C++ 所撰写而成,这个Bootstrap Loader所做的初始工作中,除了也做一些基本的初始化动作之外,最重要的就是加载定义在sun.misc 命名空间底下的Launcher.java 之中的ExtClassLoader( 因为是inner class ,所以编译之后会变成Launcher$ExtClassLoader.class) ,并设定其Parent 为null,代表其父加载器为Bootstrap Loader 。然后Bootstrap Loader ,再要求加载定义于sun.misc 命名空间底下的Launcher.java 之中的AppClassLoader( 因为是inner class,所以编译之后会变成Launcher$AppClassLoader.class) ,并设定其Parent 为之前产生的ExtClassLoader 实例。
a. Bootstrap ClassLoader/启动类加载器
主要负责java_home/jre/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作.
b. Extension ClassLoader/扩展类加载器
主要负责java_home/jre/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作
c. System ClassLoader/系统类加载器
主要负责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.jar file:/usr/ali/java/jre/lib/i18n.jar file:/usr/ali/java/jre/lib/sunrsasign.jar file:/usr/ali/java/jre/lib/jsse.jar file:/usr/ali/java/jre/lib/jce.jar file:/usr/ali/java/jre/lib/charsets.jar file:/usr/ali/java/jre/classes ------------------------------------- /usr/ali/java/jre/lib/ext the parent of extension classloader : null extension classloader can use thess jars: file:/usr/ali/java/jre/lib/ext/emma.jar file:/usr/ali/java/jre/lib/ext/localedata.jar file:/usr/ali/java/jre/lib/ext/dnsns.jar file:/usr/ali/java/jre/lib/ext/sunpkcs11.jar file:/usr/ali/java/jre/lib/ext/sunjce_provider.jar ------------------------------------- .:/usr/ali/java/lib/dt.jar:/usr/ali/java/lib/tools.jar file:/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.iteye.com/blog/307083
http://haofenglemon.iteye.com/blog/426382
http://blog.csdn.net/zdwzzu2006/archive/2008/04/05/2253982.aspx
http://wuquanyin1011.iteye.com/blog/703842
http://hi.baidu.com/yangzhibin_bai/blog/item/78846cce1cb86b0992457ead.html
http://www.blogjava.net/clraychen/archive/2008/02/20/180868.html
分享到:
相关推荐
索引类加载器一个自定义的 JVM 类加载器,它为类路径元素编制索引,以便更快地定位类/资源。 构建: ./make-jar.sh 要使用,将indexed-classpath.jar添加到类路径并设置-Djava.system.class.loader=org.pantsbuild....
Project 提供了两个 servlet ,它们有助于调试 Java Web 应用程序中的类加载问题。 这是一个项目。 JavaEE 兼容版本 servlet 与 Servlet 3.0 规范兼容,只能在 JavaEE 6.0+ 应用程序中使用。 安装 将 Jar 文件放在 ...
标准的Java SDK中有个ClassLoader类,借助此类可以装载需要的class文件,前提是ClassLoader类初始化必须制定class文件的路径。 import关键字引用的类文件和ClassLoader动态加载类的区别: import引用类的两个特点: ...
系统类 (应用类)加载器(Application classLoader): 系统类加载器是由 Sun 的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的, 它负责将 用户类路径(java -classpath或-Djava.class....
chapter15 反射与类加载器 499 15.1 运用反射 500 15.1.1 class与.class文档 500 15.1.2 使用class.forname() 502 15.1.3 从class获得信息 503 15.1.4 从class建立对象 506 15.1.5 操作对象方法与成员 ...
JVM启动之后会启动类加载器ClassLoader ClassLoader会在硬盘上的某个位置搜索HelloWorld.class字节码文件 找到该文件则执行 找不到该文件则报错 疑问:CassLoader是在哪个位置上搜索HelloWorld.class字节码...
3.9.1 类加载器的层次 44 3.9.2 java.lang.ClassLoader和授权 46 3.9.3 java.security.SecureClassLoader 49 3.9.4 java.net.URLClassLoader 49 3.9.5 类的路径 50 3.10 java.lang.SecurityManager 51 3.10.1 使用...
3.9.1 类加载器的层次 44 3.9.2 java.lang.ClassLoader和授权 46 3.9.3 java.security.SecureClassLoader 49 3.9.4 java.net.URLClassLoader 49 3.9.5 类的路径 50 3.10 java.lang.SecurityManager 51 3.10.1 使用...
path-classloader.zip,在Java7(JSR-203)文件系统路径上工作的类加载器。在Java7(JSR-203)文件系统路径上工作的类加载器。
这3个加载器分别对应着编译器去寻找类文件的优先级别和不同的路径:BootClassLoader对应jre/classes路径,是编译器最优先寻找class的地方 ExtClassLoader对应jre/lib/ext路径,是编译器次优先寻找class的地方 ...
java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 3、int 和 Integer 有什么区别 Java 提供两种不同的类型:引用类型和原始类型(或内置...
37.classloader中,JDK的API、Classpath中的同web-inf中的class加载方式有什么区别? 38.列举三种以上垃圾回收算法,并比较其优缺点? 39.编写代码实现一个线程池 40.描述一下JVM加载class文件的原理机制? 41....
更糟糕的是,类加载器将按需加载类,并且部分类路径可能位于网络连接的另一端。 可以解决更严格的问题。 例如,JAR文件中的所有类,或JAR文件在特定程序包中定义的所有类。 无论如何,这是更常见的情况。 不幸的是...
JRE中由ClassLoader负责查找和加载程序引用到的类库,基础类库ClassLoader会到rt.jar中自动加载,其它的类库,ClassLoader在环境变量CLASSPATH指定的路径中搜索,按照先来先到的原则,放在CLASSPATH前面的类库先被...
JRE中由ClassLoader负责查找和加载程序引用到的类库,基础类库ClassLoader会到rt.jar中自动加载,其它的类库,ClassLoader在环境变量CLASSPATH指定的路径中搜索,按照先来先到的原则,放在CLASSPATH前面的类库先被...
HermGen的分布式类加载器首先在类路径中搜索类。 然后,如果无法在类路径中找到所请求的类,HermGen会向群集中的其他成员发送工作程序,以获取所请求类的字节码。 这些工作程序在其他成员上运行,并在其他成员上...
java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 6、int 和 Integer 有什么区别 Java 提供两种不同的类型:引用类型和原始类型(或...
类加载器Java 程序是为 JVM Internals 2015 格但斯克大学编写的 ##关于程序 我们必须编写在应用程序的生命周期内替换类定义的程序。 这种替换应该在没有用户参与的情况下进行。 应用程序,实际上覆盖了 ClassLoader...
Eclipse 项目加载器一个用于随时加载 Eclipse 项目资源而无需重新加载项目的 ClassLoader。 它可以通过在Eclipse的调试配置中指定-Djava.system.class.loader=...
实现思路:加载实体类的class文件到classLoader中,读取实体类的属性和注解,将类名、属性字段名、注解三者与模版进行结合生成最终的代码。 1.配置 (1)配置模版路径,这个配置可以配置用于生成代码的velocity模版...