Java基础——ClassLoader

ClassLoader是用来处理类加载的类,它管理着具体类的运行时上下文。 classloader是通过分层的关联方式来管理运行中使用的类,不同的classloader中管理的类是不相同的,或者即便两个类毫无二致(除了路径)也是不同的两个类,通俗的说就是,不同的类加载器加载的,即使是同一个类,也是不同的。所以,通过classloader的限制,我们可以建立不同的package路径以区别不同的类。那么也是因为有特定的classloader,我们可以实现具体模块的加载,而不影响jvm中其他类。

一.启动类加载器(BootstrapClassLoader)

负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即时放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被java程序直接引用。

BootstrapClassLoader用于在启动JVM时加载类,以使JVM能正常工作,因而它是用Native代码实现的,最早被创建出来。

二.扩展类加载器(ExtensionClassLoader)

负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用该类加载器。

Extension ClassLoader搜索特定的标准扩展目录。该标准扩展目录在不同的JVM实现中不一定相同,在sun的JVM中,它是%JRE_HOME%
\lib\ext,具体路径可以通过java.ext.dirs系统属性值获取。该标准扩展目录存在的目的在于扩展和共享,应用程序厂商可以将部分共享库放置于此,而不是各自程序的目录下的多份拷贝。在开发过程中,我们也可以把部分常用的库放置于此,而不必每次都去配置环境。

三.应用程序类加载器(ApplicationClassLoader)

负责加载用户路径上所指定的类库,开发者可以直接使用这个类加载器,也是默认的类加载器。SystemClassLoader搜索CLASSPATH中配置的目录和jar文件。

四.三种类加载器的关系与双亲委派

JVM在加载类时默认采用的是双亲委派机制。通俗的说,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载,除了顶层的启动累加载器外,其他的类加载器都有自己的父类加载器。要注意的是这些类加载器的父子关系一般不会以继承的关系来实现,而都是以组合的关系来复用父加载器的代码。

类加载器的顺序是:

先是bootstrap classloader,然后是extension classloader,最后才是system
classloader。从设计的角度,这其实就是一种职责链模式(Chain ofResponsibility Pattern)。

Java为什么需要这种模型呢?

答案是出于安全的考虑。Java是一种安全的编程语言,它会对每个加载的类执行安全检查,但是对Java核心库中的类是不执行安全检查的(即他们是受JVM信赖的)。(什么是安全检查?以我现在所知,就是用户可以通过securitymanager来控制特定目录的访问权限,如何使用这些控制将会是另一个主题。对安全检查是否还有其他的呢?)那么假如用户可以加载自己编写的和核心库同名的类(如java.lang.Object),那么这些用户编写的类就可以绕过安全检查,从而为一些恶意用户提供了一种破坏的途径。然而在使用这种代理模型后,类的加载首先会代理到BootstrapClassLoader中实行加载,如果它发现当前核心类库中可以加载对应的类,系统会加载核心库中的类,而不会加载用户编写的类。

但是如果只是这样,还不足以保证类的加载的安全。因为用户完全可以定义自己的ClassLoader,在自己的ClassLoader中破坏这种代理模型,那么用户自己写的java.lang.Object就可以被加载了。为了解决这个问题,在Java中认为两个类名相同的实例,如果加载他们的ClassLoader不同,那么他们是不同的类型,即他们之间不能转换,而且用instanceof操作符返回的是false。这样的话,即使用户加载了自己的java.lang.Object类,它也不是系统认为可以信赖的java.lang.Object,那么它就绕不过安全检查机制。

五、其他

其实,双亲委派机制并不是一个强制性的约束模型,而是java设计者推荐给开发者的类加载器实现方式。在java中大部分的类加载器都遵循这个模型,但是有例外,比如:JDBC、JNDI、JCE、JAXB、JBI等。

现在大热的OSGI也违背了双亲委派的原则,使用了更加复杂的网站结构。因为OSGI实现模块化热部署的关键是自定义的类加载器,每一个模块都有自己的类加载器,更换Bundle时,把Bundle连同类加载器一起换掉来实现代码的热替换。

这些有关原理的东西,我们也要稍微了解一点,“不怕不知道就怕不知道”。了解了这些我们能更好的理解java的双亲委派机制和内部系统执行的流程。

不足之处,敬请指正。

时间: 2024-10-15 19:37:56

Java基础——ClassLoader的相关文章

Java基础—ClassLoader的理解

##默认的三个类加载器 Java默认是有三个ClassLoader,按层次关系从上到下依次是: - Bootstarp ClassLoader - Ext ClassLoader - System ClassLoader Bootstrap ClassLoader是最顶层的ClassLoader,它比较特殊,是用C++编写集成在JVM中的,是JVM启动的时候用来加载一些核心类的,比如:`rt.jar`,`resources.jar`,`charsets.jar`,`jce.jar`等,可以运行下

Java基础—ClassLoader的理解(转)

默认的三个类加载器 Java默认是有三个ClassLoader,按层次关系从上到下依次是: Bootstrap ClassLoader Ext ClassLoader System ClassLoader Bootstrap ClassLoader是最顶层的ClassLoader,它比较特殊,是用C++编写集成在JVM中的,是JVM启动的时候用来加载一些核心类的,比如:rt.jar,resources.jar,charsets.jar,jce.jar等,可以运行下面代码看都有哪些: URL[]

Java基础之ClassLoader类加载器简介

classloader简介 1 classloader层次结构(父子关系) Bootstrap(ClassLoader) ExtClassLoader AppClassLoader XXXClassLoader 详见代码如下: sun.misc.Launcher public Launcher() { Launcher.ExtClassLoader var1; try { var1 = Launcher.ExtClassLoader.getExtClassLoader(); } catch (I

Java基础知识之类加载器

1.类加载器定义 1.1类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制.JVM中用来完成上述功能的具体实现就是类加载器.类加载器读取.class字节码文件将其转换成java.lang.Class类的一个实例.每个实例用来表示一个java类.通过该实例的newInstance()方法可以创建出一个该类的对象. 1.2类的生命周期: 类从加载到虚拟

Java 基础:认识&理解关键字 native 实战篇

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 泥瓦匠初次遇见 navicat 是在 java.lang.Object 源码中的一个hashCode方法: 1 public native int hashCode(); 为什么有个navicat呢?这是我所要学习的地方.所以今天泥瓦匠想要总结下navicat. 一.认识 native 即 JNI,Java Native Interface 凡是一种语言,都希望是纯.比如解决某一个方案都喜欢就单单这

java基础问题总结

1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一是过程抽象,二是数据抽象. 2.继承: 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类).派生类可以从它的基类那里继承方法和实例变量,并

Java基础串理

今天抽了些时间翻阅资料复习一下Java部分基础知识,现整理笔记在此以备巩固. Java主要应用领域 –企业级应用:主要指复杂的大企业的软件系统.各种类型的网站.Java的安全机制以及它的跨平台的优势,使它在分布式系统领域开发中有广泛应用.应用领域包括金融.电信.交通.电子商务等. –Android平台应用:Android应用程序使用Java语言编写.Android开发水平的高低很大程度上取决于Java语言核心能力是否扎实. –移动领域应用,主要表现在消费和嵌入式领域,是指在各种小型设备上的应用,

java基础-java核心知识库

1.Spring.mvc的优势,原理,流程 2.Mybatis的原理优势 3.集合里面那些对象的原理 4.扩容原理,特别是map的底层 5.Hashmap.Hashtable和cocurrentHashMap的区别,要讲出它们各自的实现原理才行,比如Hashmap的扩容机制.cocurrentHashMap的段锁原理.多线程安全性. 6.几种造线程池的方法,区别 7.线程有哪几种状态,他们是如何转换的 8.Rpc原理,以及大致流程 9.Nio和netty的区别,为什么netty的性能高,nio,

Java基础知识——类装载器与反射机制

类装载器ClassLoader 类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示的对象组件. 类装载器把一个类装入JVM中,要经过三步: 1.装载:查找和导入Class文件: 2.链接:执行校验.准备和解析(解析是可以选择的): 3.初始化:对类的静态变量.静态代码块执行初始化工作: 类装载工作由ClassLoader及其子类负责.JVM在运行时会产生三个ClassLoader:根装载器.ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器). 根装