当前位置:首页 > 开发 > 编程语言 > Java > 正文

Java 类装入原理

发表于: 2009-06-21   作者:Dead_knight   来源:转载   浏览次数:
摘要: 一、类装入基础 存在三种类装入器,分别装入三种不同应用类 引导类装入器 扩展类装入器 系统类装入器 类装入器首先判断要求它装入的类是否与过去装入的类相同。如果相同,就返回上次返回的类(即保存在缓存中的类)。如果不是,就把装入类的机会交给父类。这两步递归地以深度优先的方式重复。如果父类返回 null(或抛出 ClassNotFoundException),那么类装入器会在自己的路径中寻找类
一、类装入基础
存在三种类装入器,分别装入三种不同应用类
引导类装入器
扩展类装入器
系统类装入器
类装入器首先判断要求它装入的类是否与过去装入的类相同。如果相同,就返回上次返回的类(即保存在缓存中的类)。如果不是,就把装入类的机会交给父类。这两步递归地以深度优先的方式重复。如果父类返回 null(或抛出 ClassNotFoundException),那么类装入器会在自己的路径中寻找类的源。
因为父类类装入器总是先得到装入类的机会,所以类装入器装入的类最靠近根。这意味着所有核心引导类都是由引导装入器装入的,这就保证装入了类(例如 java.lang.Object)的正确版本。这也可以让类装入器看到自己或父类或祖先装入的类,但是不能看到子女装入的类。
图 1 显示了三个标准的类装入器:

图 1. 类装入器委托模型

引导类装入器(也称作基本(primordial) 类装入器)不能由 Java 代码实例化。(通常是因为它是作为 VM 本身的一部分实现的。)这个类装入器可以从启动的类路径装入核心系统类,通常是位于 jre/lib 目录的 JAR 文件。但是能用 -Xbootclasspath 命令行选项修改这个类路径。
扩展(extension) 类装入器(也称作标准扩展 类装入器)是引导类装入器的一个孩子。它的主要职责是从扩展目录装入类,通常位于 jre/lib/ext 目录。这提供了简单地访问新扩展的能力,例如不同的安全扩展,不需要修改用户的类路径即可实现。
系统(system) 类装入器(也称作应用程序 类装入器)负责从 CLASSPATH 环境变量指定的路径装入代码。默认情况下,这个类装入器是用户创建的任何类装入器的父类。这也是 ClassLoader.getSystemClassLoader() 方法返回的类装入器。

二、类装入阶段
类的装入实际上可以分成三个阶段:装入、链接和初始化
图 2 显示了这三个阶段:

图 2. 类装入的阶段

装入 阶段包括:找到必要的类(通过查找每个类路径)并装入字节码。在 JVM 中,装入阶段为类对象提供了非常基本的内存结构。在这一阶段不处理方法、字段和引用的其他类。所以,类还不能使用。
链接 是三个阶段中最复杂的一个。可以把它分成三个主要阶段:
• 字节码验证:类装入器对于类的字节码要做许多检测,以确保格式正确、行为正确。
• 类准备:这个阶段准备代表每个类中定义的字段、方法和实现接口所必需的数据结构。
• 解析: 在这个阶段,类装入器装入类所引用的其他所有类。可以用许多方式引用类:
o 超类
o 接口
o 字段
o 方法签名
o 方法中使用的本地变量
初始化 阶段,类中包含的静态初始化器都被执行。在这一阶段末尾,静态字段被初始化成默认值。
在这三个阶段末尾,类被完整地装入,可以使用了。请注意可以用惰性方式执行类装入,所以类装入过程的某些部分可能在第一次使用类的时候才执行,而不是在装入时执行。
显式装入与隐式装入
类装入的方式有两种 —— 显式 或 隐式,两者之间有些细微差异。
显式 类装入发生在使用以下方法调用装入的类的时候:
• cl.loadClass()(cl 是 java.lang.ClassLoader 的实例)
• Class.forName()(启动的类装入器是当前类定义的类装入器)
当调用其中一个方法的时候,指定的类(以类名为参数)由类装入器装入。如果类已经装入,那么只是返回一个引用;否则,装入器会通过委托模型装入类。
隐式 类装入发生在由于引用、实例化或继承导致装入类的时候(不是通过显式方法调用)。在每种情况下,装入都是在幕后启动的,JVM 会解析必要的引用并装入类。与显式类装入一样,如果类已经装入了,那么只是返回一个引用;否则,装入器会通过委托模型装入类。
类的装入通常组合了显式和隐式类装入。例如,类装入器可能先显式地装入一个类,然后再隐式地装入它引用的所有类。

三、查看装入类信息
详细输出
可以用 -verbose 命令行选项打开 JVM 的详细输出。当某些事件发生的时候(例如,类装入时),详细输出会在控制台上显示信息。要想得到额外的类装入信息,可以用详细类输出。可以用 -verbose:class 选项启动这个模式。
解释详细输出
详细输出列出已经打开的所有 JAR 文件,包括到这些 JAR 的完整路径。下面是一个示例:
...
[Opened D:\jre\lib\core.jar]
[Opened D:\jre\lib\graphics.ja]
...

所有装入的类都已经列出,同时还指出它们是从哪个 JAR 文件或目录装入的。例如:
...
[Loaded java.lang.NoClassDefFoundError from D:\jre\lib\core.jar]
[Loaded java.lang.Class from D:\jre\lib\core.jar]
[Loaded java.lang.Object from D:\jre\lib\core.jar]
...

详细类输出显示额外信息,例如在装入超类的时候,在运行静态初始化器的时候。下面是一些示例输出:
...
[Loaded HelloWorld from file:/C:/myclasses/]
[Loading superclass and interfaces of HelloWorld]
[Loaded HelloWorldInterface from file:/C:/myclasses/]
[Loading superclass and interfaces of HelloWorldInterface]
[Preparing HelloWorldInterface]
[Preparing HelloWorld]
[Initializing HelloWorld]
[Running static initializer for HelloWorld]
...

详细输出还显示一些内部抛出的异常(如果发生的话),包含堆栈跟踪。
用 -verbose 解决问题
详细输出有助于解决类路径问题,例如没有打开 JAR 文件(因此不在类路径中)或从错误的位置装入了类。

Java 类装入原理

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
将此页作为电子邮件发送 <noscript><tr valign="top"> <td width="8"><img al
这一有关 Java 编程动态方面的新的系列文章研究了执行 Java 应用程序时幕后所发生的事情。企业 Java
本文是这个新系列文章的第一篇,该系列文章将讨论我称之为 Java 编程的动态性的一系列主题。这些主
WebSphere下配置说明 was 5.1 在websphere5.1中可以通过控制台调整该应用程序的类装载顺序。具体方
所谓装载就是寻找一个类或是一个接口的二进制形式并用该二进制形式来构造代表这个类或是这个接口的c
在实际开发中,我们经常会遇到由于ClassNotFoundException、NoClassDefFoundError、NoSuchMethodExc
问题描述: 在was6.0.0.1版本下,loushang5工作流模块,在执行wsdl文件导入时,总是失败,而在weblo
在实际开发中,我们经常会遇到由于ClassNotFoundException、NoClassDefFoundError、NoSuchMethodExc
原文地址:http://www.blogjava.net/zhuxing/archive/2008/08/08/220841.html Java 类加载原理解析
1 基本信息 摘要: 每个 java 开发人员对 java.lang.ClassNotFoundExcetpion 这个异常肯定都不陌生
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号