Java中的类加载机制主要有类加载器完成。类加载器可以说是Java语言的一项创新,也是Java语言流行的重要原因之一,称为了Java体系中一块重要的基石。
类与类加载器
类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远远不限于类加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器都拥有一个独立的类名称空间。也就是说,比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。
双亲委派模型
从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种的启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全部都继承自抽象类java.lang.ClassLoader.
从Java开发人员的角度来看,类加载器还可以划分的更加细致一些,绝大部分Java程序都会使用到以下3种系统提供的类加载器
(1)启动类加载器(Bootstrap ClassLoader)
这个类加载器负责将存放在\lib目录中的,或者被-Xbootclasspath参数所指定的路径中,并且是被虚拟机识别的类库加载到虚拟机内存中。
启动类加载器无法被Java程序直接引用。
(2)扩展类加载器(Extension ClassLoader)
这个类加载器有sun.misc.Launcher$ExtClassLoader实现,它负责加载\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发这可以直接使用扩展类加载器。
(3)应用程序类加载器(Application ClassLoader)
这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。
它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用者个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
我们的应用程序都是由这3种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如下图所示。
这种层次关系称为类加载器的双亲委派模型(Parents Delegation Model)。
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里的类加载器之间的父子关系一般不会以继承的关系来实现,二是都使用组合关系来复用父加载器的代码。
双亲委派模型的工作过程是:如果一个类加载器手到了类加载的请求,它首先不会自己去尝试加载这个类,二是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的类加载请求最终都应用传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。
例如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将变得一片混乱。
双亲委派模型对于保证Java程序的稳定运行很重要,但它的实现却非常简单,实现双亲委派的代码都集中在java.lang.ClassLoader的loadClass()方法中。
源码如下:先检查是否已经被加载过,若没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父加载器加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。
类与类加载器
类加载器虽然只用于实现类的加载动作,但它在Java程序中起到的作用却远远不限于类加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器都拥有一个独立的类名称空间。也就是说,比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。
双亲委派模型
从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种的启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全部都继承自抽象类java.lang.ClassLoader.
从Java开发人员的角度来看,类加载器还可以划分的更加细致一些,绝大部分Java程序都会使用到以下3种系统提供的类加载器
(1)启动类加载器(Bootstrap ClassLoader)
这个类加载器负责将存放在\lib目录中的,或者被-Xbootclasspath参数所指定的路径中,并且是被虚拟机识别的类库加载到虚拟机内存中。
启动类加载器无法被Java程序直接引用。
(2)扩展类加载器(Extension ClassLoader)
这个类加载器有sun.misc.Launcher$ExtClassLoader实现,它负责加载\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发这可以直接使用扩展类加载器。
(3)应用程序类加载器(Application ClassLoader)
这个类加载器由sun.misc.Launcher$AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加载器。
它负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用者个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
我们的应用程序都是由这3种类加载器相互配合进行加载的,如果有必要,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如下图所示。
这种层次关系称为类加载器的双亲委派模型(Parents Delegation Model)。
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。这里的类加载器之间的父子关系一般不会以继承的关系来实现,二是都使用组合关系来复用父加载器的代码。
双亲委派模型的工作过程是:如果一个类加载器手到了类加载的请求,它首先不会自己去尝试加载这个类,二是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的类加载请求最终都应用传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
使用双亲委派模型来组织类加载器之间的关系,有一个显而易见的好处就是Java类随着它的类加载器一起具备了一种带有优先级的层次关系。
例如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将变得一片混乱。
双亲委派模型对于保证Java程序的稳定运行很重要,但它的实现却非常简单,实现双亲委派的代码都集中在java.lang.ClassLoader的loadClass()方法中。
源码如下:先检查是否已经被加载过,若没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父加载器加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. c = findClass(name); } } if (resolve) { resolveClass(c); } return c; }
发表评论
-
fastjson合并两个JSONArray
2018-08-20 01:10 0网上使用fastjson合并两个JSONArray的实例基本 ... -
通过ClassPathXmlApplicationContext启动spring容器
2018-05-27 00:21 0对于spring初学者如果想了解spring,那么最简单的方 ... -
git reflog结果分析
2018-05-23 23:50 0git reflog命令用于gitlab中查询历史提交记录, ... -
linux内核OOM源码分析
2018-05-12 21:17 1080Out Of Memory(OOM),即内存 ... -
Java map按值排序
2018-04-22 22:59 0本文提供一个排序工具类,用于Java中的map如何按照va ... -
IDEA中Enable Auto-Import如何取消
2018-05-27 17:34 3794在使用idea进行maven项目开发时,有时候修改了pom ... -
自定义RejectedExecutionHandler的实现
2018-03-12 21:07 01.RejectedExecutionHandler的 ... -
mysql悲观锁原理详解
2018-03-02 17:45 1613mysql中的锁概念 mysql ... -
ibatis两种批量删除方式
2018-02-28 16:23 0ibatis批量操作网上可以搜到到很多,但大部分都是根据某个 ... -
Java判断List中是否有重复元素
2018-02-24 16:25 0在日常Java开发过程中,我们会去判断List集合中是否存 ... -
Gson实现json与map互相转换
2018-02-23 19:04 01.什么是Gson 什么是Gson,我们从其官网上可以看到 ... -
Lambda expressions are not supported at this language level解决方案
2018-02-23 17:21 0Java8正式版本发布后,很多人希望第一时间能够在自己的ma ... -
Java Builder模式的两种实现
2018-02-08 22:06 0前话 在Java开发过程中经常会遇到有多个属性的对象,在构 ... -
linux服务查询jdk版本
2018-05-27 17:27 1768在linux环境下开发java程序的时候,有时候需要了解安 ... -
idea提交svn提示authentication required的解决方法
2017-05-10 10:18 0idea在提交svn项目代码的时候突然提示authenti ... -
Attribute 'singleton' is not allowed to appear in element 'bean' 解决方案
2017-05-05 17:00 01. 问题描述 在spring应用部署过程中抛出如下异常: ... -
python学习
2016-12-13 15:34 0函数介绍 函数 描述 cmp(x,y) ... -
java Date.setTime时间设置逆流
2017-05-05 16:42 1968业务开发过程中需要对java.util.Da ... -
maven包冲突(java.lang.NoSuchMethodError)解决
2017-02-09 11:04 7456在Java项目开发时一般会使用maven作为项目jar包依 ... -
JavaScript美术馆实例
2016-09-16 19:31 0前言 利用JavaScript和DOM去建立一个图片库, ...
相关推荐
本文将深入探讨类加载机制,包括加载、连接、初始化三个主要阶段,以及双亲委托模型和自定义类加载器等相关概念。 首先,我们来理解类加载的过程: 1. **加载**:这是类加载的第一步,类加载器根据类的全限定名...
Java反射机制是Java编程语言中一个强大的特性,它允许程序在运行时动态地获取类的信息并操作类的对象。反射机制的核心在于,它打破了编译时的束缚,使得代码具有更高的灵活性和可扩展性。在Java中,反射主要依赖于`...
主要介绍了Java的Hibernate框架中的缓存和延迟加载机制,Hibernate是注明的Java下SSH三大web开发框架之一,需要的朋友可以参考下
### 浅析JAVA异常处理机制 #### 一、Java异常处理机制概述 异常处理是Java语言中的一个重要机制,它能够确保程序在遇到不可预料的情况时仍能维持稳定运行。异常处理主要包括三个方面:捕获异常、控制程序流程以及...
常量池在Java的动态链接中起到关键作用,因为它是解析类、方法和字段引用的依据。 5. **代码段(Code Segment)**:这部分内存用于存储从硬盘上读取的源代码。 6. **数据段(Data Segment)**:存放由`static`...
【浅析J2EE应用服务器的JAVA类装载器】 Java类装载器机制是Java语言灵活性的关键组成部分,尤其在J2EE应用服务器中扮演着重要角色。理解这一机制有助于开发者更好地部署和管理应用程序,解决可能出现的部署问题。 ...
在Spring框架中,classpath加载配置文件是应用开发中常见的操作。Spring框架提供了灵活的方式来...随着技术的发展,Spring也在不断地改进其配置加载机制,了解最新的加载方式可以帮助开发者更有效地利用Spring框架。
Java匿名内部类在创建登录界面中的应用主要体现在事件监听机制和界面组件的设置上。本文将详细阐述如何利用这些技术构建一个登录窗口。 首先,Java Swing库提供了丰富的组件用于创建图形用户界面(GUI)。在创建...
3. 双亲委派模型:Java的类加载机制遵循双亲委派模型,即当一个类加载器收到加载类的请求时,它首先会将任务委托给父类加载器,只有当父类加载器无法加载时,子类加载器才会尝试自己加载。 二、自定义ClassLoader ...
在本压缩包中的"基于Java的Web开发技术浅析 (1).pdf"可能就包含了关于WAR文件的详细解析,以及如何在Web容器中部署和运行WAR文件的方法。 总的来说,Java Web开发技术是一个庞大的领域,涵盖了从服务器端编程、...
Java提供了丰富的安全性特性,如类加载器的安全检查、运行时数据区域的安全性保护、异常处理机制等,从而有效地防止了恶意代码的执行。此外,Java提供了一套安全管理器和安全策略,允许开发者对不同部分的代码实施...
整个Java对象创建过程涉及到内存的动态分配、类的加载、字段的初始化、构造函数的调用等多个步骤,这些都是Java运行时系统的核心部分。了解这些机制对于编写高效且稳定的Java应用程序至关重要。通过本文,读者可以更...
当我们通过`java 类名`命令运行一个Java程序时,JVM(Java Virtual Machine)会查找包含`main()`方法的`public`类,并执行其中的`main()`方法。由于`main()`是静态的,所以无需实例化类对象,JVM可以直接调用它。 ...
反射机制可以让程序在运行时检测或修改程序行为,这使得程序可以在运行时动态地加载类、创建对象、调用方法、访问字段等。反射机制广泛地应用于框架、测试、插件、动态代理、依赖注入等领域。 例如,在 Spring 框架...
在安全性方面,Java有一套严格的访问控制机制和安全模型,包括类加载器、安全管理器等,可以有效防止恶意代码的执行,保护用户系统的安全。此外,Java还提供了异常处理机制,使得程序在遇到错误时能够有序地恢复或...
在Spring、Hibernate等Java框架中,反射机制被广泛应用于配置加载、依赖注入、AOP(面向切面编程)等方面,极大地提高了代码的可维护性和灵活性。 总的来说,Java反射机制是Java语言的精髓之一,它使得Java具备了...
2. JVM:在有限的资源下运行Java代码,支持类装载、垃圾回收等功能,确保代码高效执行。 三、Java智能卡的开发流程 1. 定义需求:明确智能卡需要实现的功能,如电子钱包、加密服务等。 2. 设计Applet:编写符合...
Java反射机制(Reflection)是Java语言提供的一种强大的能力,它允许程序在运行时动态地获取类的信息并操作类的对象。这种机制使得Java具备了高度的灵活性和动态性,尤其是在处理未知类或者需要根据条件动态调用类的...