虚拟机中对象的创建过程
-
当JVM遇到一条字节码new指令的时候,会会检查这个类是否已经被加载,如果没有加载则通过类加载机制加载对应的.class文件 加载完的.class类信息是分配在方法区的
-
加载成功后,开始分配内存
- 分配内存有几种方式
- 一种是指针碰撞,这种方式使用的垃圾回收机制是带垃圾整理
- 一种是空闲列表,这种方式 使用的垃圾回收机制是标记算法
- 分配内存会有多线程,所以会有线程安全问题,解决方法
- 通过CAS来处理,失败继续CAS
- 本地线程分配缓存(每次开启一个线程就会给该线程分配一块内存)(TLAB),基本都是用这种方式
- 分配内存有几种方式
-
内存空间初始化: 比如如果是int类型零值就是0 如果bool零值就是false
-
设置: 设置对象属于哪个实例,在这里是设置对象头信息
- 对象头
- 存储对象自身运行时的数据: 比如GC年龄,哈希码,锁状态标识,锁线程信息,偏向线程的id,偏向时间戳
- 类型指针
- 如果是数组,还会记录数组长度
- 实例数据: 自身里的一些数据
- 对齐填充: 内存管理对内存大小是有要求是8的整数
- 对象头
-
对象初始化: 执行类的构造方法,并实例化数据
判断内存存活
逃逸分析
可达性分析(根可达GC roots): 比如静态变量,线程栈变量(局部变量表),JNI指针等…
各种引用
- 强引用 可当处GC roots
- 软引用 只有在发生OOM的时候才会回收这个
- 弱引用 只在发生GC就会回收
- 虚引用 监控垃圾回收器是否正常工作
对象分配策略
空间担保: 就是当新生代进入老年代的时候不需要每次晋级老年代都进行fullGC,这时JVM会有一个空间担保,直接分配过来,真的不够了再进行FULLGC
垃圾回收算法与垃圾回收器
新生代用的一般是: 复制回收算法
老年代用的一般是: 标记清除和整理算法
JVM中常见的垃圾回收器有
第一代: serial 和SerialOld 单线种回收, 适用内存不大
第二代: Parallel Scavenge Parallel Old 多线程并行,可以跑多个
第三代 ParNew CMS多线程并发 垃圾回收线程和用户线程可以一起跑
第四代: G1
CMS垃圾回收图解 (CMS不是内存达到100%才会回收的,会留一定的空闲内存就执行垃圾回收)
缺点:会产生浮动垃圾 CPU也比较敏感, 还有产生内存碎片