共计 966 个字符,预计需要花费 3 分钟才能阅读完成。
JVM 运行时数据区域
名词解释
- 程序计数器(Program Counter Register):线程私有,存储每个线程的 JVM 指令,不存储 native 方法内容。方法报错的时候异常栈能告诉在代码的哪一行,就是程序计数器的功能。
- 虚拟机栈(VM Stack):每个线程私有,存储方法调用栈和线程局部基本类型变量。栈帧保存对堆内对象的引用。
- 堆(Heap):线程共享,存储对象实例,GC 就是回收这一部分。由于堆区域线程共享,对象在堆中分配需要加锁,这个操作增大开销,所以会先做逃逸分析,将线程本地小对象尝试在 TLAB(Thread Local Allocation Buffer)中分配,如果不能才去堆中的 Eden 分配。TLAB 默认是 Eden 的 1%,大对象在 TLAB 放不下,就在 Eden 分配了,所以多个小对象可能比一个大对象分配要快。
- 运行时常量池(Runtime Constant Pool):在方法区中分配,类的常量信息,方法引用信息,字符串常量等。
堆内结构
简单地说,新对象出生在 Eden,如果 Eden 不够了,触发 gc(Minor GC)把存活的对象搬到 s0,下次 gc 又搬到 s1,再下次又搬到 s0,如此往复,一个对象被搬到一定次数就是几岁,达到这个阈值就进入老年代。(默认 15 岁,就是一个狗狗的寿命)老年代满了也会 gc(Major GC/Full GC)
GC 算法
- Mark-Sweep 标记清除算法
顾名思义,两个阶段,先标记不被引用的对象,再清除掉,腾出内存。就像把围棋里被吃掉的棋子提出来。
缺点:空间碎片多
- Copying 复制算法
把空间等分两块,一块满了将所有活着的对象复制到另一个块空间,再一次清理掉之前的空间。
优点:解决了碎片问题
缺点:可用内存变低了
- Mark-Compact 标记整理算法
标记之后,把存活的对象都移动到内存一端,把端边界以外的内存空间清理掉。
没有碎片,也能充分利用内存空间。老年代通常使用这种算法。
回收目标
引用计数为空的对象:每个对象有引用计数器,有引用就 +1,引用失效就 -1,为 0 则不可能再被使用。
GC root 引用链搜索不到的对象:以 GC root 的对象为起点,沿它的引用搜索,引用链中搜索不到的对象也不会被使用。
参考文章:
https://www.cnblogs.com/zhouy…
https://www.cnblogs.com/wjtai…
正文完
发表至: java
2019-07-03