JVM学习之类加载
该文使用Hotspot JDK1.7
一、类加载器
1、什么是类加载器
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。完成类加载的家伙就是类加载器。
2、都有哪些类加载器
package com.jalja.org.base.classLoader; public class Test01 {
public static void main(String[] args) {
ClassLoader loader=Test01.class.getClassLoader();
while(loader!=null){
System.out.println(loader.getClass().getName());
loader=loader.getParent();//获取父类加载器
}
System.out.println(loader);
}
} 结果:
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
null
由输出结果可以看出ExtClassLoader是AppClassLoader的父类,而ExtClassLoader的父类却是null,原因是ExtClassLoader的父类加载器是BootStrap,BootStrap是JVM最底层的引导类加载器用C语言编写的,所以找不到一个确定的返回父Loader的方式,于是就返回null。
为什么要有这个引导类加载器:
类加载器也是java类,他们也需要类加载器加载进入内存,显然必须要有第一个不是java类的类加载器,来完成这个工作,这个正是BootStrap。
JVM中类加载器的结构:
3、各个类加载器的作用
BootStrap ClassLoader(启动类加载器):负责加载存放在D:\Program Files (x86)\Java\jdk1.7.0_79\jre\lib下,或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库(如rt.jar,所有的java.*开头的类均被Bootstrap ClassLoader加载)。启动类加载器是无法被Java程序直接引用的。
Extension ClassLoader(扩展类加载器):该加载器由sun.misc.Launcher$ExtClassLoader实现,它负责加载D:\Program Files (x86)\Java\jdk1.7.0_79\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库(如javax.*开头的类),开发者可以直接使用扩展类加载器。
Application ClassLoader(应用程序类加载器):该类加载器由sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。
4、JVM类加载机制(JVM需要加载一个类时,到底会派出哪个类加载器去执行?)
•全盘负责,当前线程的类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用CLassLoader.loadClass()指定类加载器来载入
•父类委托,先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类。所以我们在开发中尽量不要使用与JDK相同的类(例如自定义一个java.lang.System类),因为父类加载器中已经有一份java.lang.System类了,它会直接将该类给程序使用,而你自定义的类压根就不会被加载。
双亲委派模型:
双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,
只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
双亲委派机制:
1、当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrap ClassLoader去完成。
3、如果BootStrap ClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。
双亲委派模型意义:
-系统类防止内存中出现多份同样的字节码
-保证Java程序安全稳定运行
•缓存机制,缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效。
5、自定义类加载器
二、类的加载
1、类的加载:
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。
字节码(.class)文件来源:
– 从本地系统中直接加载
– 通过网络下载.class文件
– 从zip,jar等归档文件中加载.class文件
– 从专有数据库中提取.class文件
– 将Java源文件动态编译为.class文件
2、类加载的过程
JVM将javac编译好的class文件加载到内存中,并对该数据进行验证、解析和初始化,最终形成JVM可以直接使用的JAVA类型的过程。
(1)、加载:加载阶段其实就是JVM通过一个类的全限定名来获取其定义的二进制字节流,并将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构且在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。在该阶段我们开发人员可以干预,例如:我们可以指定类加载器来加载该字节数组或者自定义类加载器来加载。
(2)、链接:将java类的二进制代码合并到JVM的运行状态中的过程
a、验证:验证是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
b、准备:该阶段是在方法区中为类变量(static变量)分配内存并设置类变量初始值。例如:public static int flag=1;该阶段初始化值为0。
c、解析:虚拟机将常量池中的符号引用替换为直接引用的过程。(直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄)
(3)、初始化:初始化为类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始化。
- 初始化阶段就是执行类构造器<clinit>()的过程,类构造器<clinit>()是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。
- 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先初始化其父类。
- 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。
- 当访问一个java 类的静态域时,只有正真申明这个域的类才会被初始化。
类的初始化时机:
- 当虚拟机启动则一定会加载main方法所在的类
package com.jalja.org.base.classLoader;
public class A {
public static int width=100;
static{
System.out.println("静态代码块");
}
public static void main(String[] args) { }
}
结果:
静态代码块
- 当初始化一个类时,如果其父类未被初始化则一定先初始化其父类
package com.jalja.org.base.classLoader;
public class Demo {
public static void main(String[] args) {
A a=new A();
}
}
class A extends FatherA{
static{
System.out.println("静态代码块A");
}
}
class FatherA{
static{
System.out.println("静态代码块FatherA");
}
} 结果:
静态代码块FatherA
静态代码块A
- new一个对象的时候类被加载
- 调用类的静态方法和静态成员变量(除了final常量 常量在编译阶段就存入调用类的常量池中,所以无需初始化类)
- 使用java.lang.reflect包中的方法进行反射调用类会被初始化
类的被动引用不会初始化类:
- 调用final常量不会初始化应为 常量在编译阶段就存入调用类的常量池中,所以无需初始化类。
- 通过数组定义的类引用不会初始化类
package com.jalja.org.base.classLoader;
public class Demo {
public static void main(String[] args) {
A[] as=new A[10];
}
}
class A{
static{
System.out.println("静态代码块A");
}
}
无结果输出
- 当访问一个静态变量时,只有正真声明这个静态变量的类才会被初始化(通过子类调用父类的静态变量,子类不会被初始化)
package com.jalja.org.base.classLoader;
public class Demo {
public static void main(String[] args) {
System.out.println(A.width);
}
}
class A extends FatherA{
static{
System.out.println("静态代码块A");
}
}
class FatherA{
public static int width=100;
static{
System.out.println("静态代码块FatherA");
}
} 结果:
静态代码块FatherA
100
(4)、卸载
Java虚拟机将结束生命周期的时机:
- 执行了System.exit()方法
- 程序正常执行结束
- 程序在执行过程中遇到了异常或错误而异常终止
- 由于操作系统出现错误而导致Java虚拟机进程终止
JVM学习之类加载的更多相关文章
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- JVM学习笔记——类加载过程
JVM学习笔记——类加载过程 类加载模型——双亲委派模型(Parents Delegation Model)也可称为“溯源委派加载模型” Java的类加载器是一个运行时核心基础设施模块,主要是启动之初 ...
- JVM学习笔记——类加载和字节码技术篇
JVM学习笔记--类加载和字节码技术篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的类加载和字节码技术部分 我们会分为以下几部分进行介绍: 类文件结构 字节码指令 编译期处理 类 ...
- JVM学习--(六)类加载器原理
我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...
- JVM学习记录-类加载时机
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是类的加载机制. 在Java语言里面,类型的加载.连接和初始化过程都 ...
- JVM学习记录-类加载的过程
类的整个生命周期的7个阶段是:加载(Loading).验证(Verification).准备(Preparation).解析(Resolution).初始化(Initialization).使用(Us ...
- JVM学习记录-类加载器
前言 JVM设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外面去实现,以便让应用程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类 ...
- [jvm学习笔记]-类加载过程
JVM类加载的过程 加载=>验证=>准备=>解析=>初始化 5个阶段所执行的具体动作 加载 在加载阶段,虚拟机需要完成3个事情1.通过一个类的全限定名获取定义此类的二进制字节流 ...
- JVM学习笔记——类加载器与类加载过程
类加载器与类加载过程 类加载器ClassLoader 类加载器 ClassLoader 用于把 class 文件装载进内存. 启动类加载器(Bootstrap ClassLoader): 这个类加载使 ...
随机推荐
- 结合social relationship的推荐系统(持续更新)
最近看了一些结合社会关系的推荐系统,把论文罗列一下: (TidalTrust) Generating predictive movie recommendations from trust in so ...
- Discuz教程:X3.1-x3.2后台admin.php防止直接恶意访问
功能说明:admin.php是discuz默认的后台地址,正常情况下可以直接访问,为了防止某些恶意访问的情况,可以修改以下内容进行安全性能提升.适用版本:Discuz!x1-x3.2具体实施方案: a ...
- bootstrap 按钮 文本 浮动 隐藏
bootstrap 按钮 文本 浮动 隐藏 <!DOCTYPE html> <html lang="en"> <head> <meta c ...
- Core Audio 在Vista/Win7上实现
应用范围:Vista / win7, 不支持XP 1. 关于Windows Core Auido APIs 在Windowss Vista及Windows 7操作系统下,微软为应用程序提供了一套新的音 ...
- php之 人员的权限管理(RBAC)
1.想好权限管理的作用? 2.有什么权限内容? 3.既然有权限管理那么就会有管理员? 4.登录后每个人员的界面会是不一样的? 一.想好这个权限是什么? 就做一个就像是vip的功能,普通用户和vip用户 ...
- CI Weekly #12 | 微信小程序的自动化测试进阶
岁末将至,站在年终冲刺的尾巴上,flow.ci 新增了个人和团队设置的功能: 上线团队功能,注册时默认创建一个与用户名一致的团队,可设置:团队名称.增减团队成员,后续会不断完善: 增加个人设置,可修改 ...
- 【转】OSX键盘快捷键
OS X 键盘快捷键 了解有关常见 OS X 键盘快捷键的信息.键盘快捷键是通过按下键盘上的组合键来调用 OS X 功能的一种方式. 若要使用键盘快捷键或按键组合,您可以同时按修饰键和字符键.例如,同 ...
- HDU1494(dp)
跑跑卡丁车 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- angular表格分页
<!doctype html> <html lang="en" > <head> <meta charset="UTF-8&qu ...
- quagga源码学习--BGP协议对等体连接tcp md5签名认证选项
bgp使用tcp连接,每个bgp实例自身是peer的一个tcp server端,同时也是peer的tcp client端. 1.在bgp_create之后都建立自己的socket服务端开始监听179端 ...