`
dasheng
  • 浏览: 148558 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java类加载机制的简单知识

阅读更多

java是具有动态性,什么是动态性?有个最直观的例子:windows系统的即插即用,支持即插即用的设备可以在系统不重新启动的情况下既可以热把插使用。而java的动态性表现在:我们的程序可以不用全盘的重新编译就能对程序某部分进行更新,C#也和java一样具有动态性,而且它的这种动态性表现更为直观:直接生成windows的动态连接库文件--dll文件。而java生成的是class文件,class是怎么实现动态性的了,这个时候就全靠我们今天的主角:java的类加载器。

我们都知道所有的java类都是继承了object这个类,在object这个类中有一个方法:getclass(),这个方法返回的是一个Class类对象。一旦一个类被载入JVM中,同一个类就不会被再次载入了(切记,同一个类)。这里存在一个问题就是什么是"同一个类"?正如一个对象有一个具体的状态,即标识,一个对象始终和其代码(类)相关联。同理,载入JVM的类也应该有一个具体的标识,我们知道:在JAVA中,一个类用其完全匹配类名 (fully qualified class name)作为标识,这里指的完全匹配类名是包名和类名。不过在JVM中一个类是用其全名再附加上一个加载类ClassLoader的实例作为唯一标识。因此,如果一个名为Pg的包中,有一个名为Cl的类,被类加载器KlassLoader的一个实例对象kl1加载,生成Cl的对象,即C1.class (这里指类,而非对象)在JVM中表示为(Cl, Pg, kl1)。这意味着两个类加载器的实例(Cl, Pg, kl1) 和 (Cl, Pg, kl2)是不同的,被它们所加载的类也因此完全不同,互不兼容的。(我在项目中就真的遇到这样的情况,老是报找不到类的错误,但明明已经引入了所需包。后来才发现是不兼容)

在java中每个类都是由某个类加载器的实体来载入的,因此在Class类的实体中,都会有字段记录载入它的类加载器的实体(当为null时,其实是指 Bootstrap ClassLoader)。 在java类加载器中除了引导类加载器(既Bootstrap ClassLoader),所有的类加载器都有一个父类加载器(因为他们本身自己就是java类)。而类的加载机制是遵循一种委托模式:当类加载器有加载类的需求时,会先请求其Parent加载(依次递归),如果在其父加载器树中都没有成功加载该类,则由当前类加载器加载。

java的类加载器分为以下几种:
1,Bootstrap ClassLoader,用C++实现,一切的开始,是所有类加载器的最终父加载器。负责将一些关键的Java类,如java.lang.Object和其他一些运行时代码先加载进内存中。

2,ExtClassLoader,用java实现,是Launcher.java的内部类,编译后的名字为:Launcher$ ExtClassLoader.class 。此类由Bootstrap ClassLoader加载,但由于Bootstrap ClassLoader已经脱离了java体系(c++),所以Launcher$ExtClassLoader.class的Parent(父加载器) 被设置为null;它用于装载Java运行环境扩展包(jre/lib/ext)中的类,而且一旦建立其加载的路径将不再改变。

3,AppClassLoader,用java实现,也是是Launcher.java的内部类,编译后的名字为:Launcher$ AppClassLoader.class 。AppClassLoader是当Bootstrap ClassLoader加载完ExtClassLoader后,再被Bootstrap ClassLoader加载。所以ExtClassLoader和AppClassLoader都是被Bootstrap ClassLoader加载,但AppClassLoader的Parent被设置为ExtClassLoader。可见Parent和由哪个类加载器来加载不一定是对应的。
个类装载器是我们经常使用的,可以调用ClassLoader.getSystemClassLoader() 来获得,如果程序中没有使用类装载器相关操作设定或者自定义新的类装载器,那么我们编写的所有java类都会由它来装载。而它的查找区域就是我们常常说到的Classpath,一旦建立其加载路径也不再改变。

4,ClassLoader:一般我们自定义的ClassLoader从ClassLoader类继承而来。比如:URLClassloader是 ClassLoader的一个子类,而URLClassloader也是ExtClassLoader和AppClassLoader的父类(注意不是父加载器)。 URLClassloader的父加载器是AppClassLoader。


让我们先回到java的动态性,实现java的动态性有两种方法类型:一种是隐式,另一种是显式。什么是隐式?new 这个关键字我们都认识,当我们用其将类实例化时(即将对象载入),这种就是隐式!我们再来看显式的实现方法,一种可以由java.long.Class里面的forName()方法将类实例化,其中也用到了类加载器,详情见:认识java的Class类,另一种是由也就是直接用类加载器ClassLoader来实现。

ClassLoader一些重要的方法

A) 方法 loadClass
ClassLoader.loadClass() 是 ClassLoader 的入口点。该方法的定义如下:
Class loadClass( String name, boolean resolve );
参数name JVM 需要的类的名称,如 Person 或 java.lang.Object。
参数 resolve 参数告诉方法是否需要解析类。在准备执行类之前,应考虑类解析。并不总是需要解析。如果 JVM 只需要知道该类是否存在或找出该类的超类,那么就不需要解析详情见:认识java的Class类中的forName()方法的介绍。

B) 方法 defineClass
defineClass 方法是 ClassLoader 的主要诀窍。该方法接受由原始字节组成的数组并把它转换成 Class 对象。原始数组包含如从文件系统或网络装入的数据。defineClass 管理 JVM 的许多复杂、神秘和倚赖于实现的方面 -- 它把字节码分析成运行时数据结构、校验有效性等等。不必担心,您无需亲自编写它。事实上,即使您想要这么做也不能覆盖它,因为它已被标记成final的。

C) 方法 findSystemClass
findSystemClass 方法从本地文件系统装入文件。它在本地文件系统中寻找类文件,如果存在,就使用 defineClass 将原始字节转换成 Class 对象,以将该文件转换成类。当运行 Java 应用程序时,这是 JVM 正常装入类的缺省机制。(Java 2 中 ClassLoader 的变动提供了关于 Java 版本 1.2 这个过程变动的详细信息。) 对于定制的 ClassLoader,只有在尝试其它方法装入类之后,再使用 findSystemClass。原因很简单:ClassLoader 是负责执行装入类的特殊步骤,不是负责所有类。例如,即使 ClassLoader 从远程的 Web 站点装入了某些类,仍然需要在本地机器上装入大量的基本 Java 库。而这些类不是我们所关心的,所以要 JVM 以缺省方式装入它们:从本地文件系统。这就是 findSystemClass 的用途。

D) 方法 resolveClass
正如前面所提到的,可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的 loadClass 时,可以调用 resolveClass,这取决于 loadClass 的 resolve 参数的值。

E) 方法 findLoadedClass
findLoadedClass 充当一个缓存:当请求 loadClass 装入类时,它调用该方法来查看 ClassLoader 是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。应首先调用该方法。

怎么组装这些方法
1) 调用 findLoadedClass 来查看是否存在已装入的类。
2) 如果没有,那么采用那种特殊的神奇方式来获取原始字节。
3) 如果已有原始字节,调用 defineClass 将它们转换成 Class 对象。
4) 如果没有原始字节,然后调用 findSystemClass 查看是否从本地文件系统获取类。
5) 如果 resolve 参数是 true,那么调用 resolveClass 解析 Class 对象。
6) 如果还没有类,返回 ClassNotFoundException。

Java 2 中 ClassLoader 的变动
1)loadClass 的缺省实现
定制编写的 loadClass 方法一般尝试几种方式来装入所请求的类,如果您编写许多类,会发现一次次地在相同的、很复杂的方法上编写变量。 在 Java 1.2 中 loadClass 的实现嵌入了大多数查找类的一般方法,并使您通过覆盖 findClass 方法来定制它,在适当的时候 findClass 会调用 loadClass。 这种方式的好处是您可能不一定要覆盖 loadClass;只要覆盖 findClass 就行了,这减少了工作量。

2)新方法:findClass
loadClass 的缺省实现调用这个新方法。findClass 的用途包含您的 ClassLoader 的所有特殊代码,而无需要复制其它代码(例如,当专门的方法失败时,调用系统 ClassLoader)。

3) 新方法:getSystemClassLoader
如果覆盖 findClass 或 loadClass,getSystemClassLoader 使您能以实际 ClassLoader 对象来访问系统 ClassLoader(而不是固定的从 findSystemClass 调用它)。

4) 新方法:getParent
为了将类请求委托给父代 ClassLoader,这个新方法允许 ClassLoader 获取它的父代 ClassLoader。当使用特殊方法,定制的 ClassLoader 不能找到类时,可以使用这种方法。
父代 ClassLoader 被定义成创建该 ClassLoader 所包含代码的对象的 ClassLoader。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/skyremember/archive/2009/03/07/3967081.aspx

分享到:
评论

相关推荐

    类加载机制PPT+代码

    类加载机制是Java虚拟机(JVM)运行时的核心机制之一,它负责将类的.class文件从磁盘或网络中加载到内存,并转化为可以执行的Java对象。这一过程包括加载、验证、准备、解析和初始化五个阶段,下面我们来详细探讨...

    Java 动态加载jar文件示例

    首先,我们需要理解Java的类加载机制。Java中的类是由类加载器(ClassLoader)负责加载的。默认情况下,Java虚拟机(JVM)提供了三个内置的类加载器:启动类加载器(Bootstrap ClassLoader)、扩展类加载器...

    Java类加载内幕

    Java 的类加载机制是其核心特性之一,虽然不是经常被提及的热门话题,但对于每一位 Java 开发者来说,掌握这一机制的工作原理至关重要。本文旨在深入剖析 Java 类加载的过程,帮助读者理解类加载的基本概念及其在 ...

    JVM实战-JVM类加载机制案例分析

    本次实验的主要目的是深入理解Java虚拟机(JVM)中的类加载机制。通过实践操作,掌握类的加载、连接与初始化过程,了解不同类型的类加载器及其工作原理,学会创建自定义的类加载器,并对类的卸载有所认识。实验将结合...

    java自定义类加载classloader文档,包括代码

    本文将深入探讨Java中的类加载机制,并通过一个具体的自定义类加载器的例子来帮助理解其工作原理。 #### 二、Java类加载器的基本概念 Java中的类加载器主要负责完成以下三个基本任务: 1. **加载(Loading)**:...

    java热加载Class文件.zip

    3. **JVM ClassLoading机制**: 要实现热加载,必须理解JVM的类加载机制。Java程序中的类由类加载器负责加载,加载过程包括加载、验证、准备、解析和初始化五个阶段。热加载技术通常会干预这个过程,使得已经加载的类...

    类加载机制与动态代理的测试题

    ### 类加载机制与动态代理知识点解析 #### 一、选择题知识点详解 ##### 1. 类加载的过程 类加载过程主要包括以下几个步骤: - **加载**(A):这是类加载的第一个阶段,在这个阶段,JVM负责读取类的二进制数据到...

    java面试题--反射机制

    动态加载类是Java反射机制的重要应用场景之一。通过`Class.forName()`方法或者`ClassLoader`的`loadClass()`方法,可以根据类名字符串在运行时加载类。 #### 七、操作成员 - **创建对象**:使用`Class`对象的`new...

    java程序员需要掌握的知识点

    - **类加载机制**:了解类是如何被加载到JVM中的,包括双亲委派模型等概念。 - **性能调优**:学习如何使用工具监控JVM性能并进行调优,例如使用JVisualVM、JConsole等工具。 #### 3. 框架与技术栈 熟练掌握常见的...

    Java核心知识整理.pdf

    作为Java工程师,需要掌握Java的多方面知识点,包括但不限于JVM(Java虚拟机)原理、Java内存模型、垃圾回收机制、引用类型、集合框架、输入输出流(IO/NIO)以及类加载机制等。 JVM(Java虚拟机) JVM是Java程序...

    java知识点总结

    JVM负责内存管理、垃圾回收、类加载等任务,确保程序的高效运行。 1.3. JAVA目录 Java项目的典型目录结构包括src(源代码目录)、bin(编译后的类文件目录)、lib(库文件目录)等,遵循Java标准的目录布局有利于...

    java 反射机制知识点

    Java的反射机制是Java编程语言的核心特性之一,它允许程序在运行时动态地获取类的信息并操作类的对象。反射机制提供了对Java类的自我检查能力,使得开发者可以在不知道类的具体名称的情况下,创建和操作类的对象。 ...

    java基础知识详解 Java入门必看 Java面试题集锦

    2. **JVM原理**:理解内存模型(堆、栈、方法区等),垃圾回收机制,类加载过程等。 3. **设计模式**:学习单例、工厂、观察者等常见设计模式,提高代码复用性和可维护性。 4. **Spring框架**:如果涉及Web开发,...

    Java中高级核心知识全面解析(精华必看)

    Java语言的主要特点是:简单性、面向对象、健壮性、安全性、高效性、可移植性、多线程支持以及动态性。它通过虚拟机(JVM)实现跨平台运行,并使用自动内存管理来避免内存泄漏。 **1.1 JVM、JDK与JRE** JVM(Java ...

    Java软件保护机制的研究与实现.pdf

    综上所述,本文提出的Java软件保护机制的研究与实现,是通过一系列综合性的技术手段,包括序列号授权、类文件加密、自定义加载器以及代码混淆等,有效提高了Java软件的安全性和知识产权保护能力。这不仅有助于保护...

    Java所有知识要点

    - **动态**:支持运行时加载类和扩展。 **Java 垃圾回收机制** - Java 自动管理内存,不需要程序员手动释放内存资源。 **Java 之父** - **詹姆斯·高斯林 (James Gosling)**:被誉为“Java 之父”。 #### 二、JDK...

    JAVA的考核知识点.docx

    了解Java类的概念,对象、引用、this关键字的作用,类包的概念等,能够熟练使用类加载、类方法、类成员变量、类构造器等。 6. 抽象类与接口: 了解Java抽象类和接口的概念,能够使用抽象类和接口进行编程。 7. 内部...

    关于java热部署知识.doc

    Java的类加载机制遵循双亲委派模型,即当一个类加载器需要加载类时,它首先会委托其父类加载器尝试加载,只有在父类加载器无法加载时,才会自己加载。这种机制确保了基础类库的一致性和安全性,防止不同加载器加载的...

    Java知识(精华总结)

    2. Java语言由Sun Microsystems的James Gosling于1995年推出,其设计目标是“简单、面向对象、健壮、安全、高性能”。Java的特点包括:一次编写,到处运行(Write Once, Run Anywhere, WORA)、垃圾回收机制、自动...

Global site tag (gtag.js) - Google Analytics