jvm 调优参考: https://www.cnblogs.com/csniper/p/5592593.html
1.JVM以及GC
JVM分为:虚拟机栈、本地方法栈、堆、方法区、程序计数器
本地方法栈:用于支持native方法的执行,存储了每个native方法的执行状态。
虚拟机栈 :占用的是操作系统内存,每个线程对应一个虚拟机栈,它是线程私有的,生命周期和线程一样,
每个方法被执行时产生一个栈帧(Statck Frame),栈帧用于存储局部变量表、动态链接、操作数和方法出口等信息,当方法被调用时,方法的调用到结束对应着栈帧的入栈到出栈。
堆 区 : 是GC最频繁的,也是理解GC机制最重要的区域。堆区由所有线程共享,在虚拟机启动时创建。堆区主要用于存放对象实例及数组,所有new出来的对象都存储在该区域。
方法区 : 存放了要加载的类的信息(如类名、修饰符等)、静态变量、构造函数、final定义的常量、类中的字段和方法等信息。方法区是全局共享的,在一定条件下也会被GC。当方法区超过它允许的大小时,就会抛出OutOfMemory:PermGen Space异常。
程序计数器: 是线程私有的,记录正在执行的虚拟机字节码指令地址。
1.2 堆内内存的垃圾回收
堆内内存是java垃圾收集器的主要工作区域,为了提高垃圾回收的效率,
在堆内内存的内部又划分出了新生代、老年代和永久代。在新生代内存中又按照8:1:1的比例(java虚拟机默认分配比例为8:1:1,这个比例也可以自定义)划分出了Eden, Survivor1, Survivor2三个区域。
在一些特定的时间点,Java虚拟机会进行一次彻底的垃圾回收(full gc)。彻底回收时,垃圾收集器会对所有分配的堆内内存进行完整的扫描,在扫描期间,绝大部分正在运行的java线程都会被暂时停止。
这意味着:这样一次垃圾收集对Java应用造成的影响,跟堆内内存所存储的数据的多少是成正比的,过大的堆内内存会影响Java应用的性能。
GC:
判断一个对象是否需要回收:引用计数法,可达性分析。
GC算法:复制算法,标记-清除,标记-整理
GC回收器:
新生代: serial,parnew,parallel(吞吐量优先)
老年代: serial old,parallel old,CMS
新生代+老年代:G1(官方推荐)
新生区
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。
新生区又分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace) ,所有的类都是在伊甸区被new出来的。
幸存区有两个: 0区(Survivor 0 space)和1区(Survivor 1 space)。
当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),
将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0区。
若幸存 0区也满了,再对该区进行垃圾回收,然后移动到 1 区。
那如果1 区也满了呢?再移动到养老区。若养老区也满了,那么这个时候将产生Major GC(FullGC),进行养老区的内存清理。
若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”。
如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二:
(1)Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。
(2)代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。 ----内存溢出;内存泄漏
2. 堆外内存(off-heap memory)
2.1 堆外内存的产生
为了解决堆内内存过大带来的长时间的GC停顿的问题,以及操作系统对堆内内存不可知的问题,java虚拟机开辟出了堆外内存(off-heap memory)。堆外内存意味着把一些对象的实例分配在Java虚拟机堆内内存以外的内存区域,这些内存直接受操作系统(而不是虚拟机)管理。这样做的结果就是能保持一个较小的堆,以减少垃圾收集对应用的影响。同时因为这部分区域直接受操作系统的管理,别的进程和设备(例如GPU)可以直接通过操作系统对其进行访问,减少了从虚拟机中复制内存数据的过程。
2.2堆外内存的优缺点:
优点 :
- 可以很方便的自主开辟很大的内存空间,对大内存的伸缩性很好
- 减少垃圾回收带来的系统停顿时间
- 直接受操作系统控制,可以直接被其他进程和设备访问,减少了原本从虚拟机复制的过程
- 特别适合那些分配次数少,读写操作很频繁的场景
缺点 :
- 容易出现内存泄漏,并且很难排查
- 堆外内存的数据结构不直观,当存储结构复杂的对象时,会浪费大量的时间对其进行串行化。