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)这个程序来做的.虚拟机按以下顺序搜索并装载所有需要的类:
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 Loader,Bootstrap Loader 是由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.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
分享到:
相关推荐
JVM类加载过程 JVM(Java Virtual Machine)是Java语言的核心组件之一,它是Java语言的可移植性和跨平台性的基础。JVM主要组成部分包括类加载子系统、执行引擎、本地方法接口和运行时数据区。 类加载子系统是JVM的...
通过重写 `findClass()` 方法,我们可以打印出加载类的路径,从而跟踪加载过程。这将显示类是如何按照双亲委派模型逐级传递的。 1.4 Java 程序动态扩展方式 Java 程序的动态扩展主要依赖于类加载器的灵活性。用户...
#### 二、JVM加载Class文件的过程分析 在深入探讨之前,我们首先了解Java类加载器(ClassLoader)的基本概念。Java类加载器是JVM的重要组成部分之一,它负责查找并加载类文件到JVM的内存空间中。Java程序的运行依赖...
类加载器之间遵循委托机制,即下级类加载器先请求上级类加载器加载类,如果上级无法加载,则再由下级尝试加载。 3. **类的命名空间及运行时包**:类的命名空间是指在JVM中每个类都有唯一的标识符,防止命名冲突。...
JVM加载class文件的原理机制是Java中的核心机制之一,由于Java中的所有类必须被装载到JVM中才能运行,这个装载工作是由JVM中的类装载器完成的。类装载器所做的工作实质是把类文件从硬盘读取到内存中。 类加载机制 ...
java JVM 类加载-初始化 过程
当一个类加载器接收到加载类的请求时,它首先会委托父类加载器尝试加载,只有当父类加载器无法加载时,当前类加载器才会尝试自己加载。这样设计的目的是保证Java核心类库的稳定性,防止用户自定义类覆盖系统核心类。...
例如,可以从网络上加载类,或者实现热部署等高级功能。 五、类加载的工具与实践 在Java开发中,类加载相关的工具和框架如JUnit、Spring等,都会利用类加载机制实现其功能。例如,Spring的CGLIB和ASM库可以动态...
总结来说,JVM是Java编程的重要组成部分,它的启动过程涉及到类加载、验证、准备、解析和初始化等多个阶段。理解这些原理有助于我们更好地编写和调试Java代码,提升程序性能。通过深入研究JVM,开发者可以更好地解决...
在Java虚拟机(JVM)中,字节码自动加载是一项关键功能,它使得Java程序能够在运行时动态地发现和加载类。字节码是由Java源代码编译而成的二进制格式,它包含了类和接口的信息。了解JVM如何自动加载字节码对于深入...
JVM加载class文件的原理机制 JVM加载class文件的原理机制是Java虚拟机中一个非常重要的组件,负责将class文件加载到内存中,以便Java程序的执行。下面是JVM加载class文件的原理机制的详细介绍: 类加载的原理 在...
系统类加载器在加载类时,会先尝试让扩展类加载器加载,如果扩展类加载器无法加载,则再由系统类加载器自己尝试加载。这样的设计是为了保证核心类库的唯一性和安全性,避免用户自定义的类覆盖了 JDK 内置的核心类。 ...
- 压缩文件加载:从`.jar`、`.zip`等压缩文件中查找并加载类,自动解析`.jar`文件中的`.class`文件。 - 动态编译:从`.java`源代码文件编译成`.class`文件,然后加载。 类加载器的层次结构包括引导类加载器...
《JVM加载一个类的过程详解》 Java虚拟机(JVM)在运行Java程序时,首先需要将类的字节码加载到内存中并进行一系列处理,这一过程被称为类加载。类加载涉及到多个阶段,包括加载、验证、准备、解析和初始化等,每个...
JavaRebel是一款强大的JVM热加载插件,它极大地提升了Java开发者的生产力,尤其是在进行Web应用编程时。这款工具允许开发者在代码修改后立即看到结果,而无需重新启动服务器或重新部署应用程序。这一特性显著减少了...
验证阶段是链接过程的第一步,目的是确保加载的类文件信息符合JVM规范且不会危害虚拟机的安全。验证包括四个子步骤: - 文件格式验证:检查是否符合.class文件格式,如魔术数字、版本号等。 - 元数据验证:确保类...
当类加载器加载类之后,类需要通过一系列安全检查后才能运行。这些安全检查包括文件格式验证、元数据验证、字节码验证、符号引用验证等。 综上所述,JVM的类加载器子系统是复杂且精细的,它涉及到了类的加载、验证...
双亲委派模型的工作流程是:从顶层的Bootstrap ClassLoader开始,逐级向下尝试加载类,直到找到能加载的类为止。 通过深入JDK源码,我们可以更清晰地理解类加载机制的细节,从而在遇到问题时能迅速定位并解决。对于...