java类加载详解
1,类的加载过程;
JVM将类加载过程分为三个步骤:装载(load),链接(link)和初始化(initialize),其中链接又分为三个步骤;
验证(varification),准备(Preparation),和解析(Resolution);如下图

其实 类从被加载到虚拟机内存中开始,直到卸载出内存为止,它的整个生命周期包括了:加载、验证、准备、解析、初始化、使用和卸载这7个阶段。其中,验证、准备和解析这三个部分统称为连接(linking)。

a:装载:装载 阶段 是类加载 的第一个阶段,在此阶段虚拟机要 完成三件事情
1、 通过一个类的全限定名来获取定义此类的二进制字节流,也就是查找并加载类的二进制数据;。
2、 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3、 在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。
加载阶段即可以使用系统提供的类加载器在完成,也可以由用户自定义的类加载器来完成。
加载阶段与连接阶段的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始。
JVM在内存 中的 表现形式:

b 验证:
验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
Java语言本身是相对安全的语言,使用Java编码是无法做到如访问数组边界以外的数据、将一个对象转型为它并未实现的类型等,如果这样做了,
编译器将拒绝编译。但是,Class文件并不一定是由Java源码编译而来,可以使用任何途径,
包括用十六进制编辑器(如UltraEdit)直接编写。如果直接编写了有害的“代码”(字节流),而虚拟机在加载该Class时不进行检查的话,就有可能危害到虚拟机或程序的安全。
不同的虚拟机,对类验证的实现可能有所不同,但大致都会完成下面四个阶段的验证:

c 准备:
备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进行分配。
准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在Java堆中。
public static int value=123;//在准备阶段value初始值为0 。在初始化阶段才会变为123 。
d 解析:
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
符号引用(Symbolic Reference):符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。
直接引用(Direct Reference):直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用是与虚拟机实现的内存布局相关的,如果有了直接引用,那么引用的目标必定已经在内存中存在。
e 初始化:
类初始化是类加载过程的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码。
初始化阶段是执行类构造器<clinit>()方法的过程。<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的。
2,关于类的 初始化:什么时候才能触发初始化?
也就是 什么情况下需要开始类加载过程的第一个阶段:"加载"。虚拟机规范中并没强行约束,这点可以交给虚拟机的的具体实现自由把握,
但是对于初始化阶段虚拟机规范是严格规定了如下几种情况,如果类未初始化会对类进行初始化。
- 创建类的实例
- 访问类的静态变量(除常量【被final修辞的静态变量】原因:常量一种特殊的变量,因为编译器把他们当作值(value)而不是域(field)来对待。如果你的代码中用到了常变量(constant variable),编译器并不会生成字节码来从对象中载入域的值,而是直接把这个值插入到字节码中。这是一种很有用的优化,但是如果你需要改变final域的值那么每一块用到那个域的代码都需要重新编译。
- 访问类的静态方法
- 反射如(Class.forName("my.xyz.Test"))
- 当初始化一个类时,发现其父类还未初始化,则先出发父类的初始化
- 虚拟机启动时,定义了main()方法的那个类先初始化
1)Bootstrap ClassLoader
负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
2)Extension ClassLoader
负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
3)App ClassLoader
负责记载classpath中指定的jar包及目录中class
4)Custom ClassLoader
属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,
只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。
本文出自:http://www.cnblogs.com/javaee6/p/3714716.html http://m.blog.csdn.net/gjanyanlig/article/details/6818655
java类加载详解的更多相关文章
- Java虚拟机详解----JVM常见问题总结
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- Java Annotation详解 理解和使用Annotation
系统中用到了java注解: 查了一下如何使用注解,到底注解是什么: (1)创建方法:MsgTrace Java Class==> 在Create New Class中: name:输入MsgTr ...
- Java ClassLoad详解
Java ClassLoad详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1. ...
- Java ClassLoader详解(转载)
Java ClassLoader详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK ...
- 9种Java单例模式详解(推荐)
单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象. 懒汉式(线程不安全) 其主要表现在单例类在外 ...
- 「万字图文」史上最姨母级Java继承详解
摘要:继承是面向对象软件技术中的一个概念.它使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用. 本文分享自华为云社区<「万字图文」史上最姨母级Java继承详解丨[奔跑吧!JAVA] ...
- Java内部类详解
Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...
- 黑马----JAVA迭代器详解
JAVA迭代器详解 1.Interable.Iterator和ListIterator 1)迭代器生成接口Interable,用于生成一个具体迭代器 public interface Iterable ...
- C++调用JAVA方法详解
C++调用JAVA方法详解 博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...
随机推荐
- sklearn 中的 Pipeline 机制
转载自:https://blog.csdn.net/lanchunhui/article/details/50521648 from sklearn.pipeline import Pipeline ...
- 数学建模及机器学习算法(一):聚类-kmeans(Python及MATLAB实现,包括k值选取与聚类效果评估)
一.聚类的概念 聚类分析是在数据中发现数据对象之间的关系,将数据进行分组,组内的相似性越大,组间的差别越大,则聚类效果越好.我们事先并不知道数据的正确结果(类标),通过聚类算法来发现和挖掘数据本身的结 ...
- Kubernetes集群部署篇( 一)
K8S集群部署有几种方式:kubeadm.minikube和二进制包.前两者属于自动部署,简化部署操作,我们这里强烈推荐初学者使用二进制包部署,因为自动部署屏蔽了很多细节,使得对各个模块感知很少,非常 ...
- 用线性分类器实现预测鸢尾花的种类(python)
这是个人学习时跑的代码,结果就不贴了,有需要的可以自己运行,仅供参考,有不知道的可以私下交流,有问题也可以联系我.当然了我也只能提供一点建议,毕竟我也只是初学者 第一个页面 # -*- coding: ...
- mysql添加一个字段(
mysql添加一个字段(在指定的一个字段后面) 举个栗子:alter table inquiry add error_code varchar(3) after add_time; 说明:alter ...
- mongodb基本使用(三)
MongoDB 创建数据库 语法 MongoDB 创建数据库的语法格式如下: use DATABASE_NAME 如果数据库不存在,则创建数据库,否则切换到指定数据库. 如果你想查看所有数据库,可以使 ...
- mysql实现oracle sequence方案
转自: http://blog.csdn.net/javaGirlOne/article/details/47256183 背景:先总结一下MYSQL 自增长与ORACLE 序列的区别: 自增长只能用 ...
- Vue 列表渲染及条件渲染实战
条件渲染 有时候我们要根据数据的情况,决定标签是否进行显示或者有其他动作.最常见的就是,表格渲染的时候,如果表格没有数据,就显示无数据.如果有数据就显示表格数据. Vue 帮我们提供了一个v-if的指 ...
- 20162314 《Program Design & Data Structures》Learning Summary Of The Seventh Week
20162314 2017-2018-1 <Program Design & Data Structures>Learning Summary Of The Seventh Wee ...
- linux 常用命令-ps命令
ps(process status):进程状态相关命令 1.