Java虚拟机

Java虚拟机

Jvm机制

  • 装载具有合适的类名或者接口
  • 执行已装载的类或者接口中的指令

Jvm内存结构

  • 方法区:这块区域所有线程共享的,用来存放类的信息(如类名,修饰符),如常量,静态变量,构造函数等。GC对这块区域的回收主要是针对常量和类的装载, 在Hotspot虚拟机中,这块区域对应持久代
    但是JDK8后,持久代被删除替换为元空间,不在占用虚拟机内存

  • 堆:这块区域也是所有线程共享的,用来存放对象的实例,绝大多数创建的对象都存放在这里.垃圾回收器最主要针对的对象,对这部分的回收效率影响了VM的整体性能。

    堆中的空间划分:(基于最新的JDK8)
    - 新生代(Young Generation):包括一个Eden(伊甸园)和两个Surviver(幸存者)
    - Eden:大多数对象刚创建都会被保存在这块区域(除了部分大对象创建的时候,通过内存担保机制直接保存都Old以外).因为大多数对象都是短期内使用,
    所以会触发Minor GC[1],CG通过回收这部分区域
    - Surviver[2](个人称为亚当和夏娃):当Eden满了后进行GC,还存活的对象将复制到亚当或者夏娃其中一个,当亚当或者夏娃(假设是亚当)其中一个满了后,将会GC并把存活的对象
    复制到另外一个(这个为夏娃)的空间内,当这个(夏娃)也满了以后,会把从第一个(亚当)存活下来的对象放到Old中.
    - 老年代(Old Generation):该区域是属于老年代,一般能够在Surviver中没有被清除出去的对象才会进入到这块区域,该区域主要是采用标记清除算法[3]

  • 栈:这块区域为线程独有的,主要用来维护栈针.因为栈中的数据符合先进后出的规则,每调用一个方法就创建一个栈针,然后存放在栈中,
    方法调用完成后,把栈针释放,这样就可以继续执行后续的方法了

  • 本地方法栈:这块区域为VM的Native方法,无需关心

指令计数器

这是一个特殊的内存区域,不占用RAM,而是在CPU上,目的是保存当前字节码执行到的行号

垃圾收集器

GC主要是由垃圾收集器来进行执行的,采用不同的GC算法

  • 串行收集器:

    启用串行收集器: -XX:+UseSerialGC

新生代中使用Serial收集器采用Coping算法,单一线程进行GC,其他工作线程都挂起。
老年代中使用Serial Old收集器采用MC算法,单一线程进行GC,其他工作线程都挂起。

  • ParNew(多线程版本新生代Serial收集器):

    多线程开关: -XX:+UseParNewGC -XX:ParallelGCThreads 控制线程数量

使用Coping算法,多线程进行GC,其他工作线程都挂起

  • 并行收集器:

    启动并行收集器: -XX:+UseParallelGC (新生代用多线程、老年代用单线程)
    启动并行收集器: -XX:+UseParallelOldGC (新生代和老年代都用多线程)
    设置最大gc停顿时间: -XX:MaxGCPauseMills
    gc时间占比: -XX:GCTimeRatio
    自适应调节策略开关: -XX:+UseAdaptiveSizePolicy

新生代中使用Parallel Scavenge 采用 Coping算法,多线程进行GC,其他工作线程都挂起,但是这个收集器更加关系CPU的吞吐量,所以能控制GC时间,而ParNew不行.自适应调节策略,自动调节各种参数,新手福音
老年代中使用 Parallel Old 采用MC 算法,多线程进行GC

  • CMS收集器(Concurrent Mark Sweep):

    启用CMS收集器:-XX:+UseConcMarkSweepGC
    设置线程数:-XX:ParallelCMSThreads=n

    老年代中使用CMS采用MS算法,多线程并发,所以停顿低,速度快,但是因为采用MS算法,所以会有碎片产生

整体结构

avatar

注释


  1. 复制算法(Copying): 把所有存活的对象拷贝到另外一个空闲的空间。缺点需要额外的空闲空间 ↩

  2. Surviver: 可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能 ↩

  3. 标记清除算法(Mark-Sweep,简称MS): 首先标记出所有被使用的对象,然后清除所有未被使用的对象。最主要的缺点:整个系统挂起,并产生大量的碎片,当有大对象的时候,会再次出发GC。 ↩

你可能感兴趣的:(Java虚拟机)