JVM学习总结(1)

jvm作为java程序运行的基础平台,隐藏了底层操作系统的复杂性,使得java代码可以“一次编译,到处运行”。上层业务开发人员也不用进行处理内存等资源管理工作,提高了开发效率。但是当jvm成为程序性能的瓶颈时,或者程序发生内存溢出等问题时,如果不了解jvm虚拟机的相关知识,就不能很好地对这些问题进行处理。

一、jvm运行时内存区域

1.程序计数器

程序运行的行号指示器,所有线程共享,唯一不会发生OOM的区域。

2.虚拟机栈

java方法执行的内存模型,每个线程私有,每个方法对应一个栈帧,栈帧保存了方法执行需要的局部变量表等信息,局部变量表保存了基本数据类型和对象的引用。方法的执行对应入栈和出栈,当请求栈深度大于虚拟机允许的栈深度时,会发生StackOverflowerror,在允许动态扩展的情况下,如果申请不到足够的内存会发生OOM。

3.本地方法栈

本地方法栈和虚拟机栈类似,里面存放的是native方法信息。

4.java堆

存放java对象的区域,所有线程共享,占用内存最大,垃圾回收的主要区域。

5.方法区

主要存放被虚拟机加载的类信息,常量,静态变量等,所有线程共享。

二、jvm垃圾收集

1.发现需要收集的对象

常见的标记需要收集的对象的方法有引用计数和可达性分析

  • 引用计数:如果一个对象被引用则计数加一,引用失效是减一,最后没有引用的对象标记为可回收。缺点:无法解决循环引用问题。
  • 可达性分析:从GC Roots开始,向下搜索形成一个引用链。没有被引用链引用的对象是可回收的。

2.垃圾收集算法

  • 标记清除算法:对可回收的对象进行标记,最后进行回收。缺点:存在内存碎片。
  • 复制算法:将内存分为两块区域,使用其中一块,回收时,将不需要回收的放到另一块区域,最后将整个区域回收。优点:没有碎片问题。缺点:空间有浪费。适用于新生代的垃圾收集,因为新生代对象基本朝生夕死,存活的很少。
  • 标记整理算法:和标记清除类似,添加了整理的步骤,将不需要回收的对象整理到一起,最后回收剩下的区域。
  • 分代收集:将内存区域分为新生代和老年代,分代采取不同的回收策略,提高回收效率。

3.垃圾收集器

垃圾收集器可以分为单线程版本的新生代收集器和老年代收集器,多线程版本的单线程收集器和多线程收集器(这两类收集器在新生代均采用复制算法,在老年代采用标记整理算法),还有CMS收集器和G1收集器。
CMS以获得最短停顿时间为目标,采用标记清除算法,缺点对CPU资源敏感。G1收集器主要特点是通过并行和并发缩短停顿时间,同时使用分代收集和标记整理算法。