乐趣区

关于java:JVM参数调优

jvm 参数:

-Xms: 初始堆大小
-Xmx: 最大堆大小
当最小堆占满后,会尝试进行 GC,如果 GC 之后还不能失去足够的内存 (GC 未必会收集到所有以后可用内存),调配新的对象,那么就会扩大堆,如果 -Xmx 设置的太小,扩大堆就会失败,导致 OutOfMemoryError 谬误提醒。-Xms 能够设置与 -Xmx 雷同,以防止每次垃圾回收实现后 JVM 从新分配内存。
-Xss: 设置每个线程的堆栈大小。JDK5.0 当前每个线程堆栈大小为 1M,以前每个线程堆栈大小为 256K。更具利用的线程所需内存大小进行调整。在雷同物理内 存下,减小这个值能生成更多的线程。然而操作系统对一个过程内的线程数还是有限度的,不能有限生成,经验值在 3000~5000 左右。
-XX:NewSize=n: 设置年老代大小
-XX:NewRatio=n: 设置年老代和年轻代的比值。如: 为 3,示意年老代与年轻代比值为 1:3,年老代占整个年老代年轻代和的 1 /4
-XX:SurvivorRatio=n: 年老代中 Eden 区与两个 Survivor 区的比值。留神 Survivor 区有两个。如:3,示意 Eden:Survivor=3:2,一个 Survivor 区占整个年老代的 1 /5
-XX:MaxPermSize=n: 设置长久代大小
收集器设置
-XX:+UseSerialGC: 设置串行收集器
-XX:+UseParallelGC: 设置并行收集器
-XX:+UseParalledlOldGC: 设置并行年轻代收集器
-XX:+UseConcMarkSweepGC: 设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n: 设置并行收集器收集时应用的 CPU 数。并行收集线程数。
-XX:MaxGCPauseMillis=n: 设置并行收集最大暂停工夫
-XX:GCTimeRatio=n: 设置垃圾回收工夫占程序运行工夫的百分比。公式为 1 /(1+n)
并发收集器设置
-XX:+CMSIncrementalMode: 设置为增量模式。实用于单 CPU 状况。
-XX:ParallelGCThreads=n: 设置并发收集器年老代收集形式为并行收集时,应用的 CPU 数。并行收集线程数。

回收器抉择

JVM 给了三种抉择:串行收集器、并行收集器、并发收集器,然而串行收集器只实用于小数据量的状况,所以这里的抉择次要针对并行收集器和并发收集器。默认状况下,JDK5.0 以前都是应用串行收集器,如果想应用其余收集器须要在启动时退出相应参数。JDK5.0 当前,JVM 会依据以后系统配置进行判断。

调优总结

对 JVM 内存的零碎级的调优次要的目标是缩小 GC 的频率和 Full GC 的次数。

1.Full GC

会对整个堆进行整顿,包含 Young、Tenured 和 Perm。Full GC 因为须要对整个堆进行回收,所以比较慢,因而应该尽可能减少 Full GC 的次数。

2. 导致 Full GC 的起因

1)年轻代(Tenured)被写满

调优时尽量让对象在新生代 GC 时被回收、让对象在新生代多存活一段时间和不要创立过大的对象及数组防止间接在旧生代创建对象。

2)长久代 Pemanet Generation 空间有余

增大 Perm Gen 空间,防止太多动态对象,管制好新生代和旧生代的比例

3)System.gc()被显示调用

垃圾回收不要手动触发,尽量依附 JVM 本身的机制

调优步骤

剖析内存透露、剖析 Dump 文件、监控 GC 状态、调整 JVM 参数

1. 剖析内存透露

查看零碎产生 cpu 高和内存透露的过程,线程,找到具体产生问题的利用,定位到代码,通过优化代码来解决问题,比方,流没敞开,死循环,死锁等。

2. 剖析 dump 文件

用 jmap 生成 dump 文件,显然个别的 Window 零碎没有这么大的内存,必须借助高配置的 Linux,几种工具关上该文件:

Visual VM
IBM HeapAnalyzer
JDK 自带的 Hprof 工具
Mat(Eclipse 专门的动态内存剖析工具) 举荐应用
备注:文件太大,倡议应用 Eclipse 专门的动态内存剖析工具 Mat 关上剖析。
通过剖析 dump 内存快照文件,更加具体的全面的理解利用的 jvm 参数配置,gc 过程,oom 等。

3. 监控 GC 的状态

应用各种 JVM 工具,查看以后日志,剖析以后 JVM 参数设置,并且剖析以后堆内存快照和 gc 日志,依据理论的各区域内存划分和 GC 执行工夫,感觉是否进行优化。

举一个例子:零碎解体前的一些景象:

每次垃圾回收的工夫越来越长,由之前的 10ms 缩短到 50ms 左右,FullGC 的工夫也有之前的 0.5s 缩短到 4、5s
FullGC 的次数越来越多,最频繁时隔不到 1 分钟就进行一次 FullGC
年轻代的内存越来越大并且每次 FullGC 后年轻代没有内存被开释
之后零碎会无奈响应新的申请,逐步达到 OutOfMemoryError 的临界值,这个时候就须要剖析 JVM 内存快照 dump。
剖析后果,判断是否须要优化
如果各项参数设置正当,零碎没有超时日志呈现,GC 频率不高,GC 耗时不高,那么没有必要进行 GC 优化,如果 GC 工夫超过 1 - 3 秒,或者频繁 GC,则必须优化。

注:如果满足上面的指标,则个别不须要进行 GC 优化:

Minor GC 执行工夫不到 50ms;
Minor GC 执行不频繁,约 10 秒一次;
Full GC 执行工夫不到 1s;
Full GC 执行频率不算频繁,不低于 10 分钟 1 次;

4. 调整参数

如果内存调配过大或过小,或者采纳的 GC 收集器比较慢,则应该优先调整这些参数,并且先找 1 台或几台机器进行 beta,而后比拟优化过的机器和没有优化的机器的性能比照,并有针对性的做出最初抉择。

一直的剖析和调整

通过一直的试验和试错,剖析并找到最合适的参数,如果找到了最合适的参数,则将这些参数利用到所有服务器。

JVM 调优参数参考

1. 针对 JVM 堆的设置,个别能够通过 -Xms -Xmx 限定其最小、最大值,为了避免垃圾收集器在最小、最大之间膨胀堆而产生额定的工夫,通常把最大、最小设置为雷同的值;

2. 年老代和年轻代将依据默认的比例(1:2)调配堆内存,能够通过调整二者之间的比率 NewRadio 来调整二者之间的大小,也能够针对回收代。

比方年老代,通过 -XX:newSize -XX:MaxNewSize 来设置其相对大小。同样,为了避免年老代的堆膨胀,咱们通常会把 -XX:newSize -XX:MaxNewSize 设置为同样大小。

3. 年老代和年轻代设置多大才算正当

更大的年老代必然导致更小的年轻代,大的年老代会缩短一般 GC 的周期,但会减少每次 GC 的工夫;小的年轻代会导致更频繁的 Full GC

更小的年老代必然导致更大年轻代,小的年老代会导致一般 GC 很频繁,但每次的 GC 工夫会更短;大的年轻代会缩小 Full GC 的频率

如何抉择应该依赖应用程序对象生命周期的散布状况:如果利用存在大量的长期对象,比方高并发利用,应该抉择更大的年老代;如果存在绝对较多的长久对象,比方传输数量量大的利用,年轻代应该适当增大。但很多利用都没有这样显著的个性。

在抉择时应该依据以下两点:

(1)本着 Full GC 尽量少的准则,让年轻代尽量缓存罕用对象,JVM 的默认比例 1:2 也是这个情理。

(2)通过观察利用一段时间,看其余在峰值时年轻代会占多少内存,在不影响 Full GC 的前提下,依据理论状况加大年老代,比方能够把比例控制在 1:1。但应该给年轻代至多预留 1 / 3 的增长空间。

4. 在配置较好的机器上(比方多核、大内存),能够为年轻代抉择并行收集算法:-XX:+UseParallelOldGC**。

5. 线程堆栈的设置:每个线程默认会开启 1M 的堆栈,用于寄存栈帧、调用参数、局部变量等,对大多数利用而言这个默认值太了,个别 256K 就足用。
实践上,在内存不变的状况下,缩小每个线程的堆栈,能够产生更多的线程,但这实际上还受限于操作系统,并不能无限大。

退出移动版