一、JVM分区组成:
线程共享:堆区、方法区
线程私有:程序计数器、本地方法栈、Java虚拟机栈
1、方法区存放的是类的信息、静态变量以及常量,最重要的是运行时常量池。
2、Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,栈帧结构包括:局部变量表、操作数、返回值地址。
3、堆区存放的是对象。
二、GC(垃圾回收)
1、垃圾回收算法:标记-清除算法、复制算法、分代收集算法(最常用)
一般垃圾回收发生在堆区,堆区分为老年代和年轻代,年轻代又分为Eden、survivor1和survicor2。老年代对象的生命周期比较长,采用标记-清除算法;年轻代会有大量对象需要回收,采用复制算法,Eden和survivor1存活的对象复制到survivor2中,然后清除。长期在survivor里的对象如果没有被回收会被放到Eden中。
如果对象占用内存超过了Eden的内存,会造成JVM内存溢出。
2、对象是否存活
引用计数法:在堆中存储对象时,在对象头处维护一个counter计数器,如果一个对象增加了一个引用与之相连,则将counter++。如果一个引用关系失效则counter–。如果一个对象的counter变为0,则说明该对象已经被废弃,不处于存活状态。
缺点:很难解决对象间循环引用问题
可达性分析:通过一系列名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
如下情况的对象可以作为GC Roots:
虚拟机栈(栈桢中的本地变量表)中的引用的对象
方法区中的类静态属性引用的对象
方法区中的常量引用的对象
本地方法栈中JNI(Native方法)的引用的对象