JVM
类新建过程
1. 类加载检查
2. 分配内存
-
分配方式
- 根据内存规整的状态分配
-
指针碰撞
- 标记-整理、标记-复制算法情况下使用
- 具体:内存规整,所以直接找到第一个空闲内存指针即可
-
分配列表
- 标记-清除算法
- 具体:内存碎片较多,这些碎片区域保存在一个list中
-
并发问题
-
为什么有并发问题?
- 多线程创建对象,空间分配可能一个对象只能独占一片,导致并发问题
-
解决办法:
- 线程单独分配Eden区
- CAD
-
3. 初始化
-
给对象初始化值
- int -> 0
- …
4. 设置对象头信息
- 元数据
- hash
- GC年龄等
5. init值
- 此前阶段对于虚拟机来说已经创建了一个对象。对于Java程序来说,还不够。
- 赋值Java程序所需值
堆中内存分配的基本策略
1. Eden区
2. 幸存者区
3. 老年代区
优先分配Eden区
长期没有被回收的(默认15次)进入老年代
大对象直接进入老年代
判断对象存亡方法
程序计数器
- Java为什么没有采用
可达性分析算法
-
GCRoots
- 那些对象会标记为GCRoots
引用
强引用
软引用
弱引用
虚引用
判断废弃的常量
没有被引用的时候
判断一个无用的类
所有实例被收回
- 堆中没有实例
ClassLoader被收回
Class对象没有被引用
垃圾回收算法
标记清除
标记整理
复制
分代回收
常见的垃圾回收器
单线程
多线程
年轻代多线程、老年代多线程
并发CMS
- 初始标记
- 并发标记
- 重新标记
- 并发清除
G1
- 划分一块一块区域
类加载过程
1. 加载
- 读取class文件本质上是IO流
- 可以本地
- 可以网络
2. 连接
-
- 验证
- 2 准备
- 3 解析
3. 初始化
类加载器
-
根类加载器
- C++编写
- Javahome/lib下
- 扩展加载器
-
引用加载器
- 面向用户
双亲委派
- 加载一个类,判断是否已经加载过
- 先给父类加载,一直给到根加载器
- 顶层开始能加载则加载,不能加载则交给下一个处理
-
好处
- 避免重复加载
- 保护核心代码稳定安全