1、程序计数器
2、虚拟机栈
3、本地方法栈
1、方法区
2、java 堆 (需要优化的地方)
由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
所以说,一个进程里面有多个线程,因此有多个栈,但是所有栈共享一个堆
一个堆,多个栈
目前虚拟机基本都是采用可达性分析算法
GC Roots 的对象作为起始点,向下搜索走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链,即从GC roots 到这个对象不可达,则证明对象不可用,可被回收。
可以作为 GC Roots 的对象
在根搜索算法的基础上垃圾收集器算法主要有三种:标记-清除法, 复制算法(新生代的GC),标记-整理算法(老年代GC)。
1. 标记-清除法
分为两个阶段:标记阶段和清除阶段。在标记阶段,通过根节点,标记所有从根节点开始的可达对象,因此没有被标记的就是没有被引用的垃圾对象,然后在清除阶段,清除所有没有被标记的对象。
缺点:(1)效率低,使用递归与全堆对象遍历/还要停止程序,如果在交互式程序上体现,用户体验会很糟糕(2)这种清理出来的内存空间是不连续的,这样内存的布局就会乱七八糟
2. 复制算法(新生代的GC)
将原有的内存空间分成两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中存活的对象复制到未使用的内存中,之后清除正在使用内存块中的所有对象,然后交换两个内存块的角色,完成垃圾回收。与标记-清除法相比,复制算法更为高效。但是并不适用于存活较多的场合,比如老年代。
将内存分为一块比较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。当回收时,将Eden和Survivor中还存活着的对象一次性地复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8:1,也就是说,每次新生代中可用内存空间为整个新生代容量的90%(80%+10%),只有10%的空间会被浪费。
3. 标记-整理算法(老年代GC)
标记完后将所有的存活对象压缩到内存的一端,之后在清理边界外所有的垃圾对象。
标记/整理算法不仅可以弥补标记/清除算法当中,内存区域分散的缺点,也消除了复制算法当中,内存减半的高额代价。
但是,标记/整理算法唯一的缺点就是效率也不高。
概念:根据对象的存活周期将Java堆分为新生代和老年代,短命对象归为新生代,长命对象归为老年代。