# jvm内存模型

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈
  • 常量池(方法区)

# jVM内存管理

  • java程序可管理内存包括:堆栈

# 虚拟机栈

  • 线程启动时创建。虚拟机栈,包含多个栈帧,栈帧对应的就是调用的方法,每一个方法从调用到返回结果的过程,就是栈帧入栈和出栈的过程.
    • 栈内存的大小,是固定的。可通过-Xss参数指定
    • 运行时,成员变量和对象本身不放在栈帧中,但是它们的引用会存放在栈中。
    • 栈的变量随着变量作用域的结束而释放,不需要jvm垃圾回收机制回收。

# 栈优点

  • 栈帧之间数据不能共享,但同一个栈帧内的数据是可以共享的。
  • 存取速度快,仅次于寄存器;

# 栈缺点

  • 数据大小和生存期是确定的,缺乏灵活性.

#

  • 虚拟机启动时创建,被虚拟机内的所有线程共享;
  • 堆的唯一目的就是存放对象实例;
  • 堆是垃圾收集器活动的主要区域;

# 代际堆

  • 由于现代收集器基本都是采用的分代收集算法,所以java堆可以细分为年轻代和老年代;
  • 新生代由Eden Space和两块大小相同的Survivor Space,通常又称S0和S1,或From和To.
    • 通过参数-Xmn可指定新生代大小
    • 通过参数-XX:SurvivorRation可调整Eden和Survivor的大小
  • 老年代用于存放经过多次新生代GC仍然存活的对象.新建的大对象也可能直接进入老年代.

# 方法区

  • 存储class类的元数据信息,包括类的基本信息,字段信息,方法信息、类静态变量等;
  • 方法区存储在永久代中

# jvm参数调优

# 堆调整策略

  • jvm启动时,默认申请的最小堆内存为物理内存的1/64且小于1G;申请的最大堆内存默认为物理内存的1/4且小于1G;可通过-Xms(最小值),-Xmx(最大值)设置
  • 默认空余堆内存**小于40%时,会增大到最大堆内存大小;默认空余堆内存大于70%**时,会减小到最小堆内存大小;可通过:-XX:MinHeapFreeRation=,-XX:MaxHeapFreeRation=来指定比例;
  • 对于运行系统,为避免频繁的调整Heap大小,通常-Xms与-Xmx的值设成一样

# GC策略

注意,垃圾回收时,会触发stop-the-world,即暂停应用程序.

  • 单线程收集器
    • client模式下的默认方式;
    • 通过参数:-XX:+UseSerialGC强制指定
  • 并行收集器
    • server模式下的默认方式
    • -XX:ParallelGCThreads=20,设置并行收集的线程数目
    • -XX:+UseParallelGC,设置年轻代为并行收集
    • -XX:+UseParallelOldGC,设置老年代为并行收集
    • -XX:MaxGCPauseMillis=100,设置暂停时间,如果年轻代回收无法满足此要求,JVM会自动调整年轻代大小
  • 并发收集器
    • 与并行的区别是,只有在初始标记和二次标记时,需要stop-the-world。但收集时间很长,不能等年轻代满后才开始清理.
    • 根据官方文档,该模式需要在多CPU的情况下,才能发挥作用。一个CPU时,不如单收集器,两个CPU时,也提高不大.

# GC触发条件

  • 当eden区对象空间大于S0的空间时,发生minor gc,对整个s0,s1进行复制算法垃圾回收,并将部分对象转到Old Generation
  • 当新生代满了(eden+s0大于oldGeneration时),发生major gc或者full gc,即对新生代和老年代都进行回收

# GC参数调优建议

  • 新生代大小建议

    • 响应时间优先的应用,年轻代尽可能设大(直到达到应用系统的最低响应时间限制),因为会减少minor gc的次数。
    • 吞吐量优先的应用,年轻代尽可能设置大,可能达到Gbit的程度,因为对响应时间没有要求,垃圾收集可以并行进行,一般适合8CPU以上的应用
  • 老年代大小建议

    • 响应时间优先的应用,要综合并发会话频率、持续时间等参数

    • 吞吐量优先的应用,一般有一个很大的年轻代和一个较小的老年代

    • 老年代较小时,容易引起碎片问题