Java虚拟机基础学习

1.是不是所有的对象都在堆中分配内存?

大部分是,但并不完全是。存在逃逸的对象需要在堆中分配内存,简单而无逃逸的对象就不需要在堆中分配内存了,直接在虚拟机栈中创建对象,随着方法的出栈对象消亡。

2.什么是逃逸?

一、对象被赋值给堆中对象的字段和类的静态变量。二、对象被传进了不确定的代码中去运行。如果满足了以上情况的任意一种,那这个对象JVM就会判定为逃逸。对于第一种情况,因为对象被放进堆中,则其它线程就可以对其进行访问,所以对象的使用情况,编译器就无法再进行追踪。第二种情况相当于JVM在解析普通的字节码的时候,如果没有发生JIT即时编译,编译器是不能事先完整知道这段代码会对对象做什么操作。保守一点,这个时候也只能把对象是当作是逃逸来处理。

public class EscapeTest {

    public static Object globalVariableObject;

    public Object instanceObject;

    public void globalVariableEscape(){
        globalVariableObject = new Object(); //静态变量,外部线程可见,发生逃逸
    }

    public void instanceObjectEscape(){
        instanceObject = new Object(); //赋值给堆中实例字段,外部线程可见,发生逃逸
    }
    
    public Object returnObjectEscape(){
        return new Object();  //返回实例,外部线程可见,发生逃逸
    }

    public void noEscape(){
        synchronized (new Object()){
            //仅创建线程可见,对象无逃逸
        }
        Object noEscape = new Object();  //仅创建线程可见,对象无逃逸
    }

}
对象内存分配

1.指针碰撞法
2.空闲列表法
3.存在线程安全问题TLAB方式:
TLAB默认情况下占用了eden空间的1%
TLABWasteTargetPercent占用
年轻代占用对空间的三分之一,老年代占用堆空间的三分之二
如果需要分配的内存大小已经超过了TLAB规定的大小,此时不会采用TLAB分配好的buffer,使用CAS竞争的方式申请空间。

堆和栈之间的指向问题:

方法中生成的对象,会存在栈中变量指向堆中对象的情况
1.直接指向
一次指向,如果对象发生了变化,就需要重新指向
2.句柄指向
栈中变量指向堆中的句柄池,算是两次指向,对象发生变化后不需要重新指向

垃圾回收 GC:

识别垃圾的两种方式
  • 引用计数法 (基本上不使用,对象如果存在一次引用计数就会+1,终止引用就-1,存在循环引用的情况就不会进行垃圾回收)
  • 可达性分析法 :如果存在被GCRoot引用的对象则不被回收,不被GCRoot指向的对象则是死亡状态,可以被回收。
    (GCRoot一般指代下面五种:栈帧本地变量表、方法区常量池、方法区静态属性、活跃线程引用对象、本地方法栈JNI对象
清除垃圾的几种方式:
  • 1.标记清除法(实现简单,但是存在内存碎片,没有整理过程)
  • 2.复制算法,利用率低,只能使用一半的空间
  • 3.标记整理算法,边回收边整理,算法相对复杂
  • 4 .分代回收算法:三分之一新生代,三分之二老年代。新生代又包括eden、from、to三个区,eden区和from区存活对象移动到to区,此时from区变成to区,原来的to区变成了from区,进行一次挪动,对象的年龄+1;将eden区和原来的from区死对象进行回收,to区的年龄到达一定值就挪动到老年代中,老年代也不够用之后会进行fullGC,老年代也进行回收。占用比较大的对象也直接放到老年代。
垃圾回收器

jdk8默认的垃圾收集器是哪个:
新生代scavenge parallel(并行垃圾收集器)+老年代parallel old(并行垃圾收集器)
也可以使用新生代ParNew垃圾收集器+老年代CMS垃圾收集器
- CMS垃圾回收器

  • 1初始标记:stop-the-world(停止业务),让GC线程工作,标记GCRoots直接关联的对象, 将业务线程停止,但速度极快,几乎感应不到

  • 2并发标记阶段:并发追溯标记,程序不会停顿
  • 3重新标记:暂停虚拟机,扫描CMS堆中的剩余对象

  • 4并发清理:清理垃圾对象,程序不会停顿
  • 5并发重置:重置CMS收集器的数据结构

三色标记法:没有标记过-白色,对象标记过但是属性没有被标记过-灰色-服浮动垃圾,对象和属性都标记过-黑色;回收的时候只回收白色的

并发阶段新创建的对象自动变成黑色,重新指向新的属性不能是黑色。增量更新+写屏障避免错误标记。

G1垃圾收集器

在这里插入图片描述

g1垃圾收集器是jdk9以后取代cms垃圾收集器的垃圾收集器,也是采用三色标记法。
G1错误标记解决方案:写屏障+增量更新
1.g1垃圾收集器将整个堆空间分为大小相等的region,默认大小为1M-32M,整体采用标记整理算法,局部采用复制算法。总的region个数最大可以存在2048个,即heap最大能够达到32M*2048=64G

  • YoungGC:mixGC,年轻代的回收混杂了一些老年代的回收
    mixGC的过程:初始标记:标记出GCRoot对象,以及GCRoot所在的Region(RootRigion)

Root Region Scanning:扫表整个Region

并发标记:并发追溯标记,进行GCRootsTracing的过程
最终标记:修正并发标记期间,因为程序运行导致的标记变化的那一部分
清理回收:根据时间来进行价值最大化的回收,重置rset

G1垃圾收集器详述

G1垃圾收集器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值