`

二、我对java中类装载的理解(摘)

    博客分类:
  • JAVA
 
阅读更多

1.Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,
类装载器所做的工作实质是把类文件从硬盘读取到内存中

2.java中的类大致分为三种:
1.系统类
2.扩展类
3.由程序员自定义的类

3.类装载方式,有两种
1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中,
2.显式装载, 通过class.forname()等方法,显式加载需要的类
隐式加载与显式加载的区别:
两者本质是一样?,


4.类加载的动态性体现
一个应用程序总是由n多个类组成,Java程序启动时,并不是一次把所有的类全部加载后再
运行,它总是先把保证程序运行的基础类一次性加载到jvm中,其它类等到jvm用到的时候再加载,这样的好处是节省了内存的开销,因为java最早就是为嵌入式系统而设计的,内存宝贵,这是一种可以理解的机制,而用到时再加载这也是java动态性的一种体现

5.java类装载器
Java中的类装载器实质上也是类,功能是把类载入jvm中,值得注意的是jvm的类装载器并不是一个,而是三个,层次结构如下:
Bootstrap Loader - 负责加载系统类
|
- - ExtClassLoader - 负责加载扩展类
|
- - AppClassLoader - 负责加载应用类
为什么要有三个类加载器,一方面是分工,各自负责各自的区块,另一方面为了实现委托模型,下面会谈到该模型

6. 类加载器之间是如何协调工作的
前面说了,java中有三个类加载器,问题就来了,碰到一个类需要加载时,它们之间是如何协调工作的,即java是如何区分一个类该由哪个类加载器来完成呢。
在这里java采用了委托模型机制,这个机制简单来讲,就是“类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入,如果Parent 找不到,那么才由自己依照自己的搜索路径搜索类”,注意喔,这句话具有递归性
下面举一个例子来说明,为了更好的理解,先弄清楚几行代码:
Public class Test{
Public static void main(String[] arg){
ClassLoader c = Test.class.getClassLoader(); //获取Test类的类加载器
System.out.println(c);
ClassLoader c1 = c.getParent(); //获取c这个类加载器的父类加载器
System.out.println(c1);
ClassLoader c2 = c1.getParent();//获取c1这个类加载器的父类加载器
System.out.println(c2);
}
}
把以上代码存到d:/my 文件夹下,直接编译,然后在dos模式下运行
D:/my/java Test
。。。AppClassLoader。。。
。。。ExtClassLoader。。。
Null

D:/my

注: 。。。表示省略了内容
可以看出Test是由AppClassLoader加载器加载的
AppClassLoader的Parent 加载器是 ExtClassLoader

但 是ExtClassLoader的Parent为 null 是怎么回事呵,朋友们留意的话,前面有提到Bootstrap Loader是用C++语言写的,依java的观点来看,逻辑上并不存在Bootstrap Loader的类实体,所以在java程序代码里试图打印出其内容时,我们就会看到输出为null
【注:以下内容大部分引用java深度历险】
弄明白了上面的示例,接下来直接进入类装载的委托模型实例,写两个文件,如下:
文件:Test1.java
Public class Test1{
Public static void main(String[] arg){
System.out.println(Test1.class.getClassLoader());
Test2 t2 = new Test2();
T2.print();
}
}

文件: Test2.java
Public class Test2{
Public void prin(){
System.out.println(this.getClass().getClassLoader());
}
}

这 两个类的作用就是打印出载入它们的类装载器是谁, 将这两个文件保存到d:/my目录下,编译后,我们在复制两份,分别置于 <JRE所在目录>/classes下(注意,刚开始我们的系统下没有此目录,需自己建立) 与 <JRE所在目录>/lib/ext/classes下(同样注意,开始我们的系统下也没此目录,手工建立), 然后切换到d:/my目录下开始测试,

测试一:
<JRE所在目录>/classes下
Test1.class
Test2.class

<JRE所在目录>/lib/ext/classes下
Test1.class
Test2.class

D:/my下
Test1.class
Test2.class


dos下输入运行命令,结果如下:
D:/my>java Test1
Null
Null

D:/my>

从输出结果我们可以看出,当AppClassLoader要载入Test1.class时,先请其Parent,也就是ExtClassLoader来载 入,而ExtclassLoader又请求其Parent,即Bootstrap Loader来载入Test1.class. 由于 <JRE所在目录>/Classes目录为Bootstrap Loader的搜索路径之一,所以Bootstrap Loader找到了Test1.class,因此将它载入,接着在Test1.class之内有载入Test2.class的需求,由于 Test1.class是由Bootstrap Loader所载入,所以Test2.class内定是由Bootstrap Loader根据其搜索路径来找,因Test2.class也位于Bootstrap Loader可以找到的路径下,所以也被载入了,最后我们看到Test1.class与Test2.class都是由Bootstrap Loader(null)载入。


测试二:
<JRE所在目录>/classes下
Test1.class

<JRE所在目录>/lib/ext/classes下
Test1.class
Test2.class

D:/my下
Test1.class
Test2.class

dos下输入运行命令,结果如下:
D:/my>java Test1
Null
Exception in thread “main” java.lang.NoClassdefFoundError:Test2 at Test1.main。。。
D:/my>

从输出结果我们可以看出,当AppClassLoader要载入Test1.class时,先请其Parent,也就是ExtClassLoader来载 入,而ExtclassLoader又请求其Parent,即Bootstrap Loader来载入Test1.class. 由于 <JRE所在目录>/Classes目录为Bootstrap Loader的搜索路径之一,所以Bootstrap Loader找到了Test1.class,因此将它载入,接着在Test1.class之内有载入Test2.class的需求,由于 Test1.class是由Bootstrap Loader所载入,所以Test2.class内定是由Bootstrap Loader根据其搜索路径来找,但是因为Bootstrap Loader根本找不到Test2.class(被我们删除了),而Bootstrap Loader又没有Parent,所以无法载入Test2.class.最后我们看到Test1.class是由Bootstrap Loader(null)载入,而Test2.class则无法载入


测试三
<JRE所在目录>/classes下

Test2.class

<JRE所在目录>/lib/ext/classes下
Test1.class
Test2.class

D:/my下
Test1.class
Test2.class

dos下输入运行命令,结果如下:
D:/my>java Test1
。。。ExtClassLoader。。。
Null

D:/my>

从输出结果我们可以看出,当AppClassLoader要载入Test1.class时,先请其Parent,也就是ExtClassLoader来载 入,而ExtclassLoader又请求其Parent,即Bootstrap Loader来载入Test1.class.但是Bootstrap Loader无法在其搜索路径下找到Test1.class(被我们删掉了),所以ExtClassLoader只得自己搜索,因此 ExtClassLoader在其搜索路径 <JRE所在目录>/lib/ext/classes下找到了Test1.class,因此将它载入,接着在Test1.class之内有载 入Test2.class的需求,由于Test1.class是由ExtClassLoader所载入,所以Test2.class内定是由 ExtClassLoader根据其搜索路径来找,但是因为ExtClassLoader有Parent,所以先由Bootstrap Loader帮忙寻找,Test2.class位于Bootstrap Loader可以找到的路径下,所以被Bootstrap Loader载入了.最后我们看到Test1.class是由ExtClassLoader载入,而Test2.class则是由Bootstrap Loader(null)载入

了解了以上规则,请朋友们自行分析以下场景的执行结果

测试四:
<JRE所在目录>/classes下


<JRE所在目录>/lib/ext/classes下
Test1.class
Test2.class

D:/my下
Test1.class
Test2.class


测试五:
<JRE所在目录>/classes下


<JRE所在目录>/lib/ext/classes下
Test1.class


D:/my下
Test1.class
Test2.class


测试六:
<JRE所在目录>/classes下


<JRE所在目录>/lib/ext/classes下

Test2.class


D:/my下
Test1.class
Test2.class


测试七:
<JRE所在目录>/classes下


<JRE所在目录>/lib/ext/classes下


D:/my下
Test1.class
Test2.class


以上理解,错漏之处请朋友们及时指出,以免怠误大家

分享到:
评论

相关推荐

    java类装载

    java类装载介绍,介绍了java装载类的先后顺序

    Java虚拟机类装载的原理及实现

    - **`ClassLoader`**:这是Java中的一个抽象类,定义了几个关键的方法来支持类的装载。 - **`loadClass(String name, boolean resolve)`**:根据给定的全限定名加载类。如果resolve为true,则在类加载后会对其进行...

    Java虚拟机类装载:原理、实现与应用

    Java中的ClassLoader是一个关键角色,它负责在运行时查找和加载类文件。ClassLoader是一个抽象类,位于java.lang包下,提供了诸如`loadClass`、`defineClass`、`findSystemClass`、`resolveClass`和`findLoadedClass...

    Java虚拟机类装载.doc

    在Java中,类装载器 把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化。其中链接又可以分成校验、准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的。各个步骤的主要工作如下: * ...

    Java虚拟机类装载机制

    Java虚拟机类装载机制是Java运行环境中的核心组成部分,它负责将类的字节码从磁盘、网络等不同来源加载到JVM中,并进行一系列处理以使类能够被...同时,理解类装载机制也有助于解决运行时类冲突、类加载异常等问题。

    Java的类装载器和命名空间

    在Java编程语言中,类装载器(ClassLoader)和命名空间是理解Java运行时环境的重要概念。它们共同确保了程序的正确性和安全性。类装载器负责将类文件加载到Java虚拟机(JVM)中,而命名空间则帮助组织和管理这些类,...

    Java虚拟机类装载:原理、实现与应用.doc

    理解类装载机制对于优化程序性能、实现动态加载、插件系统以及增强程序的灵活性具有重要意义。例如,通过自定义类装载器,开发者可以在运行时替换或添加新的功能模块,而无需重启应用程序。 在实际开发中,类装载器...

    装载问题-分支限界算法-java实现

    1. 物流行业:java实现可以用于解决物流行业中的装载问题,例如货物装载、车辆装载等。 2. manufacturing行业:java实现可以用于解决 manufacturing行业中的装载问题,例如生产计划、库存管理等。 结论 java实现...

    Java深度历险(2)--深入类装载器

    在Java中,每个类都是由类装载器加载到JVM中的,并且每个类都由特定的类装载器实例加载。类装载器不仅确保了程序的动态性,还提供了强大的安全性保障。 #### 类装载器的作用 1. **动态性**:类装载器使Java程序...

    JAVA虚拟机的类装载机制的原理分析与应用研究.pdf

    在Java中,类装载器是分层的,由Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader构成,它们遵循双亲委托模型。当一个类装载器收到加载类的请求时,它首先会委托给父类装载器,只有当父类装载器无法...

    java类装载器学习一、类加载器的基本概念

    类装载器学习一、类加载器的基本概念 类装载器学习一、类加载器的基本概念 类装载器学习一、类加载器的基本概念

    Java类文件动态装载

    在Java编程语言中,类文件的动态装载是一个关键特性,它允许程序在运行时加载未知或需要在后期确定的类。这种灵活性对于实现插件系统、动态代理、反射和其他高级功能至关重要。本篇文章将深入探讨Java类文件的动态...

    Java类装载过程_.docx

    Java 类装载过程是Java虚拟机(JVM)运行的核心机制之一,...理解并掌握Java类装载过程对于进行JVM优化、编写高效代码和排查运行时错误都至关重要。同时,自定义类装载器也可以用于实现特定的安全策略或动态加载需求。

    深入理解Java虚拟机(第二版)_java_

    《深入理解Java虚拟机(第二版)》是Java开发者必读的经典著作,它全面而深入地探讨了Java虚拟机(JVM)的工作原理和技术细节。这本书涵盖了从内存管理、类加载机制、字节码执行到垃圾收集算法等多个关键领域,为...

    jvm类装载器原理

    理解类装载器的工作原理对于优化Java应用性能和实现动态加载类至关重要。 装载过程包括三个主要步骤:装载、链接和初始化。装载阶段,类装载器依据指定的全限定类名(如`java.lang.Object`)去寻找对应的二进制数据...

    [浅析J2EE应用服务器的JAVA类装载器]python回朔异常的模块.docx

    Java类装载器机制是Java语言灵活性的关键组成部分,尤其在J2EE应用服务器中扮演着重要角色。理解这一机制有助于开发者更好地部署和管理应用程序,解决可能出现的部署问题。 Java类装载器是Java虚拟机(JVM)的一...

    在Java中用类装载框架控制类加载

    摘要通过构建一个能够把Java类装载隔离到一个指定的jar文件中的类装载组件容器框架,你可以确保运行时刻会装载你期望的组件版本。Java的类装载框架强有力且具有灵活性。它允许应用程序存取类库而不必链接到静态的...

    java之jvm学习笔记五(实践写自己的类装载器)

    类装载器在Java中的主要职责是动态加载类到JVM中。Java的类装载器分为三个基本层次:启动类装载器(Bootstrap ClassLoader)、扩展类装载器(Extension ClassLoader)和应用程序类装载器(Application ClassLoader)...

Global site tag (gtag.js) - Google Analytics