java虚拟机
JVM内存区域
程序计数器:线程私有,当前线程所执行的字节码的行号指示器
虚拟机栈:线程私有,每个方法在执行时都会创建一个栈帧,存储局部变量表等信息,如果线程请求的栈深度大于虚拟机所允许的深度,就会抛出StackOverflowErro(while(true)count++;)
本地方法栈:线程私有
java堆:线程共享,存放对象实例,是内存中最大的一块,也是垃圾回收的主要区域
方法区:线程共享,存放加载的类信息、常量、静态变量
判断对象是否存活?
1.引用计数算法:给对象添加引用计数器,引用该对象,计数器加1,引用失效,计数器减1。计数器为0时,这个对象就能被回收了。会出现对象之间相互循环引用的问题。
2.可达性分析算法:通过GC roots对象作为起始点,从这些节点向下搜索,如果一个对象到GC roots没有任何引用链时,则说明该对象可以回收。
有哪些GC ROOTS
1.虚拟机栈(栈帧中的本地变量表)中引用的对象
2.方法区类静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈中(native方法)引用的对象
JVM垃圾回收算法?
标记-清除算法:标记需要回收的对象,标记完成后统一回收,清除后会产生大量内存碎片
复制算法:把内存分为大小相等的两块,当一块的的内存用完了,就把还存活的对象复制到另一块上,再把内存清掉,现在一般用这种算法来回收新生代
标记-整理算法:标记需要回收的对象,然后让存活的对象向一端移动,再把内存清掉。
分带收集算法:把内存分为新生代和老年代,因为大部分对象只存活一小段时间,新生代采用复制算法,把内存分为三块,eden空间和两个survivor空间,默认比例是8:1:1,垃圾回收一次后,存活的对象到另一块空着的survivor空间
JVM里面的垃圾回收器?
针对新生代的垃圾回收器有三个:serial、parallel new、parallel scavenge。这三个都采用的是标记-复制算法,其中serial是单线程的,parallel new可以看成是serial的多线程版本。parallel scavenge更加注重吞吐率。
针对老年代的垃圾回收器也有三个:serial old、parallel old以及cms。
因为在垃圾回收时会暂停掉所有的工作线程,那cms是一种最短停顿时间为目标的回收器,它基于标记-清除算法实现,并且是并发的,他工作的四个步骤是:初次标记、并发标记、重新标记、并发清除。初次标记是关联GC roors对象,所以虽然这个阶段需要暂停工作线程,但是速度很快。并发标记是查找GC roots对象的应用链,是并发进行的,重新标记是标记并发标记期间,工作进程运作导致的标记变动,这一个阶段也是需要stop the world。
G1是一个横跨新生代和老年代的垃圾回收器,他将堆分为多个区域,每个区域都可以充当eden、survivor区或者老年代中的一个,它采用标记-压缩算法,在进行选择回收区域时,他会优先回收死亡对象较多的区域。
类加载机制?
加载
链接
初始化
https://time.geekbang.org/column/article/11523