基础概念:
JVM是一个可运行java代码的假想计算机,包括程序计数器、虚拟机栈、本地方法栈、方法区、堆等部分组成,可以按照共享划分:
共享区:随JVM启动而创建; 堆 + 方法区
独占区:跟随线程的生命周期 程序计数器 + 虚拟机栈 + 本地方法栈

  • 程序计数器
    在多线程环境下,JVM的多线程是通过CPU的时间片轮转来实现,但是当时间片耗尽的时候,线程会被挂起,然后程序计数器会在此时记录当前线程的字节码执行位置,然后等到当前线程再次获取时间片后,从挂起的地方继续执行,记录的实际上就是当前线程挂起的字节码位置;
  1. 程序计数器有线程隔离性,线程独占
  2. 程序计数器占用内存空间非常小,可忽略不计
  3. 程序计数器是java虚拟机规范中唯一一个没有规定OutofMemeryError的区域,因为只是存了一个地址,无论如何,这个地址都不会超出限制
  4. 程序执行的时候,程序计数器有值,记录的是正在执行的字节码的地址
  5. 执行native本地方法时,程序计数器为空,因为native通过jni调用本地C/C++库实现,没有字节码文件,所以无法统计
  • :分为年轻代(堆的三分之一)+老年代(堆的三分之二)+永久代;分代是为了优化GC回收垃圾的性能
  • 年轻代:Eden + Survivor(from + to);新创建的对象一般会存在Eden中,满了以后会触发minor GC,此时大量的垃圾数据在eden中被回收,然后少部分存活的数据会被放到to区,在from区,存活次数到达指定时会被放到老年代,其他的数据会被放到to区,此时eden和from区都是空的,然后minor gc结束后,to区和from区交换角色,新的to区就是之前的from区,可以保证名为to的区域一直是空的,直到to区被填满,所有对象都移动到老年代中。
  • 年轻代的大小默认为堆的1/15,可以通过-xmn来设置固定大小
  • 存活次数通过虚拟机参数:-XX:MaxTenuringThreshold来设置
  • eden:survivor的比例是8比2,from和to各占其一
  • minor GC采用分代复制算法进行垃圾回收,可以有效地避免内存碎片,每次执行都会清理年轻代中的内存
  • 执行minor GC的时候,不会影响到永久代,从永久代到年轻代的引用被当做GC roots,从年轻代到永久代的引用在标记阶段会直接被忽略掉
  • 老年代:存放对象都是存活时间较长的,大小较大的对象,因此老年代使用的是标记整理算法进行垃圾回收机制,老年代容量满了的时候,会触发一次Major GC;
  • 标记清除算法:先从GC root进行遍历,然后标记所有可达对象,再次从GC root开始进行遍历,然后清除所有没有标记的对象,优点: 不需复制大量对象,缺点:需要中断其他线程的访问,然后可能会产生内存碎片;
  • 标记整理算法:和标记清楚大体一致:在清除最后新增了一个压缩整理,可以将存货的对象向内存的一遍压缩,这样就可以解决内存碎片的问题。老年代装满时,出现Out of Memery异常。

注:并非原创,各种资料整理而来,如有侵权请告知