jvm|生产平台必须设置的几个JVM参数,你设置了吗?

jvm|生产平台必须设置的几个JVM参数,你设置了吗?

文章图片


对于JVM参数 , 大多数JAVA程序员都是只略知皮毛而已 , 甚至很多人压根就没配置过JVM参数 , 少部分人会配置一些内存相关的参数 。 很多人并没有手动配置JVM参数的意识 , 甚至一些略有经验的码农也认为只需要使用默认的JVM参数就好了 。 事情真的是这样的吗?那显然不是的 , 不同的JVM参数配置会有效的增加工作效率 , 减轻工作量 , 所以作为一名资深JAVA程序员 , 一定要养成针对环境特点配置JVM参数的好习惯 。
那么我们来看看 , 哪些JVM参数应该在生产平台上配置吧 。
一、
HeapDumpOnOutOfMemoryError
在生产平台上 ,
HeapDumpOnOutOfMemoryError是必须要配置的重要参数之一 。 它的作用是当堆抛出OOM错误时 , dump出当前的内存堆存储快照 。 因为生产平台不同于测试环境 , 复现生产平台场景的成本非常高 , 甚至对于一些小公司来说 , 其成本并非公司所能承受 。 因此 , 在生产平台出现OOM错误时 , 保留现场的内存堆快照 , 对于定位问题 , 快速解决问题 , 具有极其重要的意义 。
二、GC相关内存配置
在jdk1 。 8以前 , 通常在生产环境要配置一下-XX:PermSize和-XX:MaxPermSize , 表示在JVM里存储Java类信息 , 常量池和静态变量的永久代(方法区) 区域初始值和最大值 。 在项目启动后 , 这个值是固定的 , 如果项目 class(类实例) 过多 , 很可能会导致OutOfMemoryError: PermGen异常 。
而在jdk1 。 8及以后 , 关于永久代的配置已经成为了-XX:MetaspaceSize和XX:MaxMetaspaceSize 。 MetaspaceSize如果不做配置 , 默认大小约21M , 而MaxMetaspaceSize最大元空间则只受本地内存大小限制 。 MetaspaceSize触发FullGC的阈值 , 默认约为21M , 如做了配置 , 最小阈值为自定义配置大小 。 空间使用达到阈值 , 触发FullGC , 同时对该值扩大 。 当然如果元空间实际使用小于阈值 , 在GC的时候也会对该值缩小 。
MaxMetaspaceSize为元空间的最大值 , 如果设置太小 , 可能会导致频繁FullGC , 甚至OOM 。

三、AutoBoxCacheMax
JAVA进程启动的时候 , 会加载rt 。 jar这个核心包 , rt 。 jar包里的Integer也同时被加载到JVM中 , Integer里面有一个IntegerCache缓存 。 其中有一个静态代码块 , JVM在加载Integer这个类时 , 会优先加载静态的代码 。 当JVM进程启动完毕后 , -128 ~ +127 范围的数字会被缓存起来 , 调用valueOf方法的时候 , 如果是这个范围内的数字 ,, 则直接从缓存取出 。 超过这个范围的 , 就只能构造新的Integer对象了 。 而利用AutoBoxCacheMax这个参数 , 可以修改这个缓存值 , 因此 , 如果项目中需要经常对更大的整数类型进行转换的话 , 那么就可以将这个参数修改得更大些 , 比如说设置成20000 。
四、AlwaysPreTouch
JAVA进程启动的时候 , 虽然我们可以为JVM指定合适的内存大小 , 但是这些内存操作系统并没有真正的分配给JVM , 而是等JVM访问这些内存的时候 , 才真正分配 , 这样会造成以下问题:
1、GC的时候 , 新生代的对象要晋升到老年代的时候 , 需要内存 , 这个时候操作系统才真正分配内存 , 这样就会加大young gc的停顿时间;
2、可能存在内存碎片的问题 。
因此 , 可以在JVM启动的时候 , 配置AlwaysPreTouch参数 , 这样JVM就会让操作系统把内存真正的分配给JVM 。 后续JVM就可以顺畅的访问内存了 。
五、MaxTenuringThreshold
MaxTenuringThreshold是年轻代晋升老年代的最大年龄阈值 。 在CMS垃圾回收机制中默认为6 , 其它垃圾回收算法里默认是15 。 并且该参数值设置之后只是初始值会动态改变 。 在GC回收的时候 。 当Eden区满了的时候 , 会触发第一次GC , 把还活着的对象拷贝到SurvivorFrom区 , 当Eden区再次触发GC的时候 , 会扫描Eden和SurvivorFrom区 , 对这两个区域进行垃圾回收 , 经过这次回收还活着的对象 , 会从From区复制到SurvivorTo区 , 同时把这些对象的年龄加1 , 当年龄达到了老年代的标准 , 就是上面所说的15或6 , 则复制到老年代去 。 注意From和To只是两个临时存储点 , 在不同的GC阶段是会互换的 。
如果将MaxTenuringThreshold设置为0 , 则年轻对象不会经过Survivor区 , 直接进入老年代 。 由于新生代使用copy算法 , 如果Survivor区存活的对象太久的话 , Survivor区存活的对象就越多 , 这个就会影响copy算法的性能 , 使得young gc停顿的时间加长 , 因此可以依据自己的生产环境 , 来设置这个值 。