JVM学习
1.JVM体系结构
-
体系
项目
JRE — JVM
操作系统
硬件体系
-
编程流程
.java—>class File—>类装载器calss Loader
- 运行时数据区
- 方法区 Method area (JVM调优)
- 堆 Heap (JVM调优)99%
- 存属性和值
- Java栈 stack (不会垃圾回收)
- 存地址
- 本地方法栈 Native Method Stack (不会垃圾回收)
- 程序计数器 (不会垃圾回收)
- 本地方法接口 JNI
- 本地方法库
- 执行引擎 (垃圾回收所处位置)
- 运行时数据区
-
类加载器作用
- 加载Class文件,实例化
2.双亲委派机制
- 自底向上检查是否已装载
- 自顶向下尝试加载类
3.沙箱安全机制
-
沙箱机制就是将Java代码限定在虚拟机特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏.
-
沙箱主要限制系统资源访问
-
组成沙箱的基本组件
- 字节码校验器
- 确保Java类文件遵循Java语言规范,但不是所有类文件都会经过字节码校验,比如核心类
- 类装载器
- 防止恶意代码去干涉善意的代码 双亲委派机制
- 守护了被信任的类库边界
- 将代码归入保护与,确定了代码可以进行哪些操作
- 存取控制器
- 存取控制器可以控制API对操作系统的存取权限,二这个控制的策略设定,可以由用户指定
- 安全管理器
- 是核心API和操作系统之技安的主要接口,实现权限控制,比存取控制器优先级高
- 安全软件包
- java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全性
- 安全提供者
- 消息摘要
- 数字签名 keytools
- 加密
- 鉴别
- java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全性
- 字节码校验器
3.Native
-
凡是带了native关键字的方法,说明是本地方法,Java作用范围达不到,去调用底层C语言的库,进入本地方法栈,调用本地方法本地接口(JNI)
-
JNI作用
- 扩展Java的使用,融合不同的编程语言为Java所用
4.PC寄存器(程序计数器)
program Counter Regiter 程序计数器
- 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法去中的方法字节码(用来指向一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计
5.方法区
method Area 方法区
-
方法去是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法去种,但是实例变量存在堆内存种,和方法区无关
static、final、Class、常量池
6.栈
线程结束,占内存也就是释放,对于栈来说不存在垃圾回收问题
一旦线程结束,栈就结束了
-
存储
- 八大基本类型
- 对象引用
- 实例方法
-
栈运行原理
- 栈帧(每执行一个方法,就会有一个栈帧)
- 方法索引
- 输入输出参数
- 本地变量
- Class File引用
- 父帧
- 子帧
一旦栈满了就会栈溢出
- 栈帧(每执行一个方法,就会有一个栈帧)
7.堆
7.1三种JVM
- HotSopot (Sun公司)
- JRockit 世上最快 (BEA公司)
- J9VM (IBM公司)
7.2堆
-
Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的
-
类加载器读取了类文件后,一般会把类,方法,变量,常量放到堆中,保存我们所有引用类型的真实对象
-
堆内存中细分为三个区域
- 新生区
- 伊甸园区
- 幸存区(过度)
- 幸存0区
- 幸存1区
- 老年区(幸存区)
- 永久区 (在JDK8以后改为元空间)
- 新生区
GC主要在新生区和老年区,内存满了会报OOM
7.2.1新生区
类诞生和成长的地方,甚至死亡
伊甸园区满后,轻GC一次,如果还有引用进入幸存者0区…
7.2.2永久区
这个取域常驻内存.用来存放JDK自身携带的CLAss对象,Interface元数据,存储的是Java运行时的一些环境
- jdk1.6之前: 永久代,常量池在方法区
- jdk1.7: 永久代,但是慢慢退化了,(去永久代),常量池在堆中
- jdk.18: 无永久代,常量池在元空间
不存在垃圾回收.关闭VM虚拟就会释放这个区域的内存
元空间:逻辑上存在;物理上不存在
-
OOM问题查看
-
尝试扩大堆内存看结果
-
分析内存,看一下哪个地方出现了问题
-
内存快照分析工具 MAT Jprofiler (看到第几行出错)
-Xms 初始内存大小 -Xmx最大内存大小 --XX:+HeapDumpOnOutOfMemoryError
- 分析Dump内存文件,快速定位内存泄露
- 获得堆中的数据
- 获得大的对象
- …
-
Dubug (一行行分析代码)
-
-
8.GC:垃圾回收
-
作用区域
- 堆
- 方法区
-
JVM进行GC时,并不是堆三个区域统一回收.大部分的时候,回收的都是新生代
-
新生区 (主要用复制算法)
- 伊甸园区
- 幸存区 to from 谁空谁是to
- 每次GC都会将伊甸园区活的对象移到幸存者区,一旦伊甸园区被GC,就会为空
-
老年区()
-
默认当一个对象经历了15次GC都没有死,会进入老年区
-XX: -XX:MaxTenuringThreshold=9999
设置进入老年区时间
-
-
-
GC两种类型
- 轻GC(普通的GC)
- 重GC(全局GC)
-
GC回收算法
-
复制算法
每次GC都会将伊甸园区活的对象移到幸存者空的区
- 优势
- 没有内存碎片
- 劣势
- 浪费内存空间(有一个幸存者区永远为空)
- 优势
-
标记清除算法
对所有对象进行扫描,对存活对象进行标记,对没有标记的对象进行清除
- 优势
- 不需要额外空间
- 劣势
- 两次扫描,严重浪费时间
- 会产生内存碎片
- 优势
-
标记清除压缩算法
标记清除算法后,再次扫描,向一端移动存活的对象
-
优势
- 不需要额外空间
- 不会产生内存碎片
-
劣势
- 多了一个移动成本
-
-
总结
-
内存效率
- 复制算法>标记清除算法>标记压缩算法(时间复杂度)
-
内存整齐度
- 复制算法=标记压缩算法>标记清除算法
-
内存利用率
- 标记压缩算法=标记清除算法>复制算法
没有最好的算法,只有最合适的算法
GC:分带收集算法
- 年轻代:存活率低 复制算法
- 老年区:区域大,存活率高 标记清除(内存碎片不是太多)+标记压缩=标记清除压缩
-
-
9.JMM
-
概念
- Java内存模型
-
作用
- 缓存一致性,用于定义数据读写的规则
…见JUC学习 https://blog.csdn.net/weixin_44783458/article/details/120070262
- 缓存一致性,用于定义数据读写的规则