Java类加载机制总结
加载(Loading)
加载过程是Java的一大特点,类的来源可以多种多样,压缩包、网络字节流、运行时动态计算生成(reflect)等等...这也造就了Java语言强大的动态特性。
java.lang.Class
验证(Verification)
这一过程主要是为了确保Class的字节流中包含的信息符合虚拟机标准,以免造成破坏
- 文件格式验证
- 元数据验证
- 字节码验证,通过数据流和控制流分析确定程序的语义是合法的
- 符号引用验证,确保解析动作能够正常执行
准备(Preparation)
这一阶段将会为类变量分配内存并设置其初始值,注意此时进行内存分配的仅包括类变量(static修饰),并且初始值通常情况下是数据类型的零值而不是设定值,如下例
public static int val = 123; 复制代码
在这一阶段变量 val
的赋值是0而不是123,因为此时尚未执行任何Java方法,而对 val
复制的 putstatic
指令在初始化阶段后才会执行。
当然也有特殊情况,如下
public static final int val = 123; 复制代码
加上final关键字修饰后,Java编译时会为 val
生成 ConstantValue
属性,这时准备阶段就会根据设置将其值设置为123。
解析(Resolution)
此阶段虚拟机将常量池内的符号替换为直接引用,主要包含以下动作:
- 类或接口的解析
- 字段解析
- 类方法解析
- 接口方法解析
初始化(Initialization)
这时类加载过程的最后一步,这部分开始真正的执行Java代码,也就是说,这个阶段可以由程序员参与。
此阶段其实就是执行类构造器 <clinit>()
方法的过程。
类加载器
类加载器(Class Loader)是Java虚拟机的一大创举,它将“获取类的二进制字节流”这个过程交给了开发人员自己去实现,只要编写不同的Class Loader,应用程序本身就可以用相应的方式来获取自己需要的类。
类与加载器的关系
对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在虚拟机中的唯一性。
通俗的讲,就是即便同一个Class文件,被不同的类加载器加载之后,得到也不是同一个“类”(equals方法返回false)。
双亲委派模型
从虚拟机角度讲,只有两种类加载器,一种是启动类加载器(Bootstrap ClassLoader),在hotpot上使用C++实现,属于虚拟机的一部分;另一种则是所有其他类的加载器,这些加载器是独立于虚拟机的,由Java语言实现的,从开发者角度看,可以分为以下两类:
-
扩展类加载器(Extension ClassLoader)
-
应用程序类加载器(Appliaction ClassLoader)
当然开发人员也可以自己编写类加载器,最终不同的类加载器之间的层次关系如下图所示:
这就是Java中著名的 双亲委派模型 ,它要求除了顶级的BootStrap加载器之外,其他类加载器都必须有父类加载器,工作流程如下:
如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器去完成,只有当父加载器反馈自己无法完成加载请求时,子加载器才会自己去尝试加载这个类。
这样做的好处是,Java类随着它的类加载器一起具备了一种带有优先级的层次关系。举个例子,比如 java.lang.Object
这个类,无论哪个类加载器加载时,最终都会委派给Bootstrap加载器去加载,这就保证了整个系统运行过程中的 Object
都是同一个类。
否则,如果用户自己编写了一个 java.lang.Object
类,并放在程序的classpath中,最终系统将会出现多个不同的Object类,整个Java体系就变得一团混乱了。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
来入门一下kotlin吧
Kotlin是什么? Kotlin是一种在java虚拟机上运行的静态类型的编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源。 Kotlin的优势! Kotlin可以编译成java字节码,也可以编译成JavaScript。方便在没有java虚拟机的主机上运行。(据说学会Kotlin,你就是一名全栈工程师 (/偷笑)) 并且的2017年的 Google I/O大会上,Google宣布将Kotlin作为Android的官方开发语言。(这就意味着,作为一名“资深‘的android开发工程师,以后就必须得会Kotlin了) Kotlin相对于java开发android有什么优势呢?(个人亲身体验) 拿辉哥的话说:一个字!简洁!(一直用java写android,当我用kotlin写了android的一个Demo之后,暂且不讨论它的底层等等,对于写法上,就是简洁!可能本章节体现的简洁不是很明显) 这一篇的入门,前提是你是有java基础的情况下。这样子你可以举一反三,才会看懂一部分。所以......往下看吧 Kotlin的使用!(这里以Android Stu...
- 下一篇
Java 读写锁 ReentrantReadWriteLock 源码分析
本文内容:读写锁 ReentrantReadWriteLock 的源码分析,基于 Java7/Java8。 阅读建议:虽然我这里会介绍一些 AQS 的知识,不过如果你完全不了解 AQS,看本文就有点吃力了。 目录 使用示例 ReentrantReadWriteLock 总览 源码分析 读锁获取 读锁释放 写锁获取 写锁释放 锁降级 总结 使用示例 下面这个例子非常实用,我是 javadoc 的搬运工: // 这是一个关于缓存操作的故事 class CachedData { Object data; volatile boolean cacheValid; // 读写锁实例 final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { // 获取读锁 rwl.readLock().lock(); if (!cacheValid) { // 如果缓存过期了,或者为 null // 释放掉读锁,然后获取写锁 (后面会看到,没释放掉读锁就获取写锁,会发生死锁情况) rwl....
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Red5直播服务器,属于Java语言的直播服务器
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音