JVM-第二章 运行时数据区(方法区、堆、程序计数器、本地方法栈、虚拟机栈)
文章目录
前言
略
一、方法区和堆
一个进程独占一份,即一个JVM虚拟机启用一个方法区和堆。程序计数器、本地方法栈、虚拟机栈则由每个线程独占一份
Hotspot JVM中的主要线程:
- 虚拟机线程。
- 周期任务线程。
- GC线程
- 编译线程
- 信号调度线程
二、PC寄存器(程序计数器)
概述:JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟,寄存器存储指令相关的现场信息
作用:PC寄存器用来存储指向下一条指令的地址,即将要执行的指令代码。有执行引擎读取下一条指令。
PC寄存器特点:
- 占用内存小,运行速度快。
- 声明周期与线程保持一致。
- 指定JVM指令地址或不指定值(native方法)。
- 相当于程序控制流的指示器。
- 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
- 不会发生GC和OOM。
举例:
三、JVM虚拟机栈
拓展:栈是运行时的单位,而堆是存储的单位,即栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。堆解决的是数据存储的问题,即数据怎么放、放在哪儿。
概述:每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧,对应一次次的Java方法调用。
特点:
是线程私有的。
生命周期和线程保持一致。
栈是一种快速有效的分配储存方式,访问速度仅次于程序计数器。
JVM对该栈的操作只有进栈和出栈两个操作。
栈的储存结构和运行原理:
- 每个线程都有自己的栈,栈中的数据都是以栈帧的格式存在。
- 在这个线程上正在执行的每个方法都各自对应一个栈帧。
- 栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息。
作用:主管Java程序的运行,它保存方法的局部变量(8种基本数据类型、对象的引用地址、部分结果,并参与方法的调用和返回)。
补充:加载.class文件的方式
从本地系统中直接加载。
通过网络获取,典型场景:Web Applet。
从zip压缩包中读取,成为日后jar、war格式的基础。
运行时计算生成(动态代理技术)。
由其他文件生成(JSP应用)。
从专有数据库中提取.class文件。
从加密文件中获取,典型的防Class文件被反编译的保护措施
1.加载
2.链接
包含三部分
- 验证
如,类的头部信息ca fa ba be - 准备
静态变量会赋予默认初始值,即零值。准备阶段不会对实例变量分配初始值 - 解析
3.初始化
初始化阶段就是执行类构造器方法clinit的过程,该方法无需定义。与init方法不同(任何一个类都至少存在一个类的构造器)。clinit方法或初始化过程会追溯到父类再依次执行。虚拟机必须保证一个类的clinit方法在多线程下被同步加锁。
三、类加载器的分类
1.分类表现形式
- JVM支持两种类型的类加载器,分别是引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader)。
- 所有派生与ClassLoader的类加载器都划分为自定义类加载器
- 常见的类加载器:引导类加载器、扩展类加载器、系统类加载器
2.启动类加载器(引导类加载器,Bootstrap ClassLoader)
- 使用C/C++语言实现的,嵌套在JVM内部
- 是用来加载Java的核心库
- 并不继承自java.lang.ClassLoader,没有父加载器
- 加载扩展类和应用程序类加载器,并指定为他们的父类加载器
- 该类加载器仅加载包名为java、javax、sun等开头的类
3.扩展类加载器(Extension ClassLoader)
- Java语言编写
- 派生于ClassLoader类
- 父类加载器为启动类加载器
- 加载目录为jre/lib/ext子目录(扩展目录)下加载类库。如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。
4.应用程序类加载器/系统类加载器(AppClassLoader)
- Java语言编写
- 派生于ClassLoader类
- 父类加载器为扩展类加载器
- 负责加载环境变量中classpath或系统属性 java.class.path指定路径下的类库。
- 该类加载是程序中默认的类加载器。
- 通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器。
5.用户自定义类加载器
使用场景:隔离加载类、修改类加载的方式、扩展加载源、防止源码泄露
6.双亲委派机制
工作原理:类的加载需要类加载器,当该类加载器接收到加载请求时,会依次调用父类加载器去进行委托加载,请求最终到达顶层的启动类加载器。父类能完成加载任务的便优先父类完成,否则才会交由子加载器进行加载。
优势:
- 保护程序安全,防止代码被篡改
- 避免类的重复加载
7.沙箱安全机制
略
8.其他
JVM判断是否是同一个类的条件:类名及全路径包名相同。所以引导的类加载器为同一个。
程序主动使用类时需要进行类的初始化,而被动使用不需要。
总结
略