Java的设计初衷是主要面向嵌入式领域,对于自己定义的一些类,考虑使用依需求载入原则。即在程序使用到时才载入类,节省内存消耗,这时就可以通过类载入器来动态载入。

假设你平时仅仅是做web开发,那应该非常少会跟类载入器打交道,但假设你想深入学习tomcatserver的架构,它是不可缺少的。所谓类载入器。就是用于载入Java类到Java虚拟机中,它负责读取Java字节码。并转换成java.lang.Class类的一个实例。使字节代码.class文件得以执行。

一般类载入器负责依据一个指定的类找到相应的字节代码,然后依据这些代码定义成一个Java类。另外还负责载入资源。包含图像文件和配置文件。

类载入器在实际使用中给我们带来的优点是。它能够使Java类动态地载入到JVM并执行。就可以在程序执行时再载入类,提供了非常灵活的动态载入方式。

比如我们熟悉的Applet,从远程server下载字节码到client动态载入到JVM便能够执行。

在Java的庞大体系中,能够将系统分为三种类载入器,各自是:

①   启动类载入器(Bootstrap ClassLoader):载入对象是Java核心库。把一些关键的Java类载入进JVM,这个载入器使用原生代码(C/C++)实现的。并非继承java.lang.ClassLoader,它是全部其它类载入器的终于父载入器,负责载入<JAVA_HOME>/jre/lib文件夹下且被JVM指定的类库。事实上它属于JVM总体的一部分,JVM一启动就将这些指定的类载入到内存中,避免以后过多的I/O操作。提高系统的执行效率。

启动类载入器无法被Java程序直接使用。

②   扩展类载入器(Extension ClassLoader):载入的对象为Java的扩展库。即载入<JAVA_HOME>/jre/lib/ext文件夹里面的类。

这个类由上面的Bootstrap ClassLoader载入,但因为Bootstrap ClassLoader并不是用Java实现,已经脱离了Java体系,所以假设尝试调用扩展类载入器的getParent()方法获取父载入器会得到null,但它的父类载入器是Bootstrap ClassLoader。

Java中能够直接使用扩展类载入器。

③   应用程序类载入器(Application  ClassLoader):亦叫系统类载入器(System ClassLoader),它负责载入用户类路径(CLASSPATH)指定的类库。假设程序没有自定义类载入器。就默认使用应用程序类载入器。它也由Bootstrap ClassLoader载入。但它的父载入类被设置成了Extension ClassLoader。

假设要使用这个载入器,可通过ClassLoader.getSystemClassLoader()获取。

假如有一天你心血来潮也想自己写一个类载入器,那么你仅仅须要继承java.lang.ClassLoader类就可以。于是能够用以下的图2-4-1来清晰表示出各种类载入器的关系,Bootstrap ClassLoader是最根本的类载入器,其不存在父类载入器,Extension ClassLoader由Bootstrap ClassLoader载入。所以它的父类载入器是Bootstrap ClassLoader。Application ClassLoader也是由Bootstrap ClassLoader载入,但它的父载入器被指向了Extension
ClassLoader,而其它全部用户自己定义的类载入器都由Application ClassLoader载入。

由此能够看出越重要的类载入器就越早被JVM载入,这是考虑到安全性。由于先载入的类载入器会充当下一个类载入器的父载入器,在双亲委派模型机制下,就能确保安全性。

那么什么是双亲委派模型?比方爷爷、爸爸、你三代单传,你们家族都遗传懒惰基因,每当遇到事情都互相推脱,如今须要一个人去买一包盐,不然今晚的菜就有色无味了。而你第一个被托付去超市买,但因为你的懒惰。你向你爸爸撒了一顿娇,你爸爸受不了你仅仅能答应帮你去,在懒惰的驱使下,你爸爸最后找了一个借口说要赶工作。让你爷爷出去走动走动顺便买一包盐,就这样你爷爷仅仅能乖乖去超市买盐。

双亲委派模型就类似这种机制。类载入器载入类时首先托付给父类载入器载入。除非父类载入器不能载入才自己载入。

这样的模型要求除了顶层的启动类载入器外,其它的类载入器都要有自己的父类载入器。假如有一个类要载入进来。一个类载入器并不会立即尝试自己将其载入,而是委派到父类载入器。父类载入器收到后又尝试委派到其父类载入器,以此类推,直到委派到启动类载入器,这样一层一层往上委派。仅仅有当父类载入器反馈自己没法完毕这个载入时,子载入器才会尝试自己载入。通过这个机制。保证了Java应用所使用的都是同一个版本号的Java核心库的类。同一时候这个机制也保证了安全性,设想假设Application ClassLoader想要载入一个有破坏性的java.lang.System类,双亲委派模型会一层层向上委派,终于委派给Bootstrap
ClassLoader,而Bootstrap ClassLoader检查到缓存中已经有了这个类。并不会再载入这个有破坏性的System类。

另外,类载入器还拥有全盘负责机制,即当一个ClassLoader载入一个类时,这个类所依赖的、引用的其它全部类都由这个ClassLoader载入,除非在程序中显性地指定另外一个ClassLoader载入。

图2-4-1 类载入器关系

在Java中。我们用全然匹配类名来标识一个类。即用包名和类名。而在JVM中。一个类由全然匹配类名和一个类载入器的实例ID作为唯一标识。

即是说同一个虚拟机能够有两个包名、类名都相同的类。仅仅要他们由两个不同类载入器载入。

于是当我们在Java中常常说两个类相不相等,必须是针对同一个类载入器载入的前提下才有意义。否则就算是相同的字节代码,由不同类载入器载入,这两个类也不是相等的。这样的特征为我们提供了隔离机制,在tomcatserver中是十分实用的。

了解了JVM的类载入器的各种机制后,看看一个类是如何被类载入器载入进来的。一个类准备载入,类载入器先推断此类是否已经被载入过(载入过的类会被缓存在内存中),假设缓存中存在此类则直接返回这个类。

否则获取父类载入器,假设父类载入器为null,则由Bootstrap ClassLoader载入并返回Class。假设父类载入器不为null,则由父类载入器载入。载入成功就返回Class,载入失败则依据类路径查找class文件,找到就载入此class并返回Class,找不到就抛出ClassNotFoundException异常。

图2-4-2 类载入过程

类载入器属于JVM级别的设计,我们非常多时候基本不会跟他打交道,可是假如你想了解整个JAVA体系是怎样工作的,假如你要设计开发自己的框架或中间件或一个较庞大的java软件。那么你必须熟悉类载入器的相关机制,在现实的设计中,依据实际情况利用类载入器能够提供类库的隔离及共享,保证你的软件不同级别的逻辑切割程序不会互相影响,提供更好的安全性。

喜欢研究java的同学能够交个朋友,以下是本人的微信号:

java类载入器——ClassLoader的更多相关文章

  1. Java类载入器 ClassLoader的解析

    //參考 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类载入器基本概念 类载入器是 Java 语言的一个创新,也是 Ja ...

  2. Java类载入器原理分析

    一:Java虚拟机中能够安装多个类载入器,系统默认是三个基本的类载入器: Bootstrap  ExtClassLoader  AppClassLoader 类载入器也是Java类.由于其它Java类 ...

  3. Java类载入器(一)——类载入器层次与模型

    类载入器   虚拟机设计团队把类载入阶段中的"通过一个类的全限定名来获取描写叙述此类的二进制字节流"这个动作放到Java虚拟机外部去实现.以便让应用程序自己决定怎样去获取所须要的类 ...

  4. Java类载入器(二)——自己定义类载入器

      用户定制自己的ClassLoader能够实现以下的一些应用: 自己定义路径下查找自己定义的class类文件,或许我们须要的class文件并不总是在已经设置好的Classpath以下,那么我们必须想 ...

  5. Java类载入器

    1.   系统载入器简单介绍 Java虚拟机中能够安装多个类载入器,系统默认三个主要类载入器(BootStrap.ExtClassLoader.AppClassLoader).每一个类载入器负责载入特 ...

  6. 黑马程序猿——Java中的类载入器

    ------- android培训.java培训.期待与您交流! -------- 类载入器 Java虚拟机中能够安装多个类载入器,系统默认三个主要类载入器,每一个类负责载入特定位置的类: BootS ...

  7. 深入研究Java类载入机制

    深入研究Java类载入机制   类载入是Java程序运行的第一步,研究类的载入有助于了解JVM运行过程,并指导开发人员採取更有效的措施配合程序运行. 研究类载入机制的第二个目的是让程序能动态的控制类载 ...

  8. Tomcat类载入器机制(Tomcat源代码解析六)

    要说Tomcat的Classloader机制,我们还得从Bootstrap開始.在BootStrap初始化的时候.调用了org.apache.catalina.startup.Bootstrap#in ...

  9. Jboss7类载入器

    1. 类载入器理论知识介绍 类载入器基于Jboss Module,代替了层次类载入环境,避免了当类存在多个版本号时,导致类载入错误. 类载入是基于模块的.必须显示的定义模块依赖.部署也是模块化的,假设 ...

随机推荐

  1. Java:获取IP地址

    文章来源:https://www.cnblogs.com/hello-tl/p/9139323.html import java.net.InetAddress; import java.net.Un ...

  2. CUDA & cuDNN环境配置

    环境 python3.5 tensorflow 1.3 VUDA  8.0 cuDNN V6.0 1.确保GPU驱动已经安装 lspci | grep -i nvidia 通过此命令可以查看GPU信息 ...

  3. LeetCode(169)Majority Element

    题目 Given an array of size n, find the majority element. The majority element is the element that app ...

  4. Postfix telnet www.azengna.com 25 Connection Refused 但是localhost连接成功

    修改配置文件 vi /etc/postfix/main.cf 原先配置信息 .... inet_interfaces = all #inet_interfaces = $myhostname,loca ...

  5. netcore使用AutoMapper

    说明:以下是使用过程中看到的其他博主写的,地址如下: 地址一:https://cloud.tencent.com/developer/article/1395155 地址二:https://www.c ...

  6. angular2 启动步骤

    以下内容转自网络 1. 创建项目文件夹 创建一个新的文件夹来保存你的项目,比如一开始有个self就好了 2.安装基础库 首先确保已经安装了node.js 我们使用 npm package manage ...

  7. SHELL二十篇(读书笔记)

    一.文件安全与权限 1.系统默认情况下建立文件与目录的权限: 系统默认情况下建立文件与目录的权限是: #vi /etc/bashrc 可以看到一般用户是002  root用户是022 说明:一般用户默 ...

  8. luogu3563 逛公园

    两遍 spfa 然后建立分层图拓扑排序 dp 一下. 写得很差劲.效率很低. 时间复杂度 \(\mathrm{O}(Tnk)\). 参见这里秒懂. #include <iostream> ...

  9. [Go]通道(channel)的基本操作

    通道类型是Go语言自带的.唯一一个可以满足并发安全性的类型,在声明并初始化一个通道时,需要用到内建函数make,传给make函数的第一个参数应该代表通道的具体类型的类型字面量. 如类型字面量 chan ...

  10. 使现有的VSCode成为便携版(绿色版)

    VSCode可以说是各种代码编辑器前端之中的神器了,相对体积小且扩展性强,我们希望将它携带在U盘中在各种工作环境中使用,官方也提供了在Windows,Linux和MacOS三大平台中使VSCode便携 ...