目录
常见配置
其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容;
其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容;
其三是非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用;
-client //client模式,启动速度比较快运行时性能和内存管理效率不高,通常用于客户端应用程序或者开发和调试。
-server //server模式,启动速度比较慢,但运行时性能和内存管理效率很高,适用于生产环境
-jar //以jar包的形式执行一个应用程序。
//jar包的manifest文件中声明初始加载的Main-class,Main-class必须有public static void main(String[] args)方法
-D<property>=<value> //系统级全局变量值,系统属性名/值对 如-Dname="space string"
-classpath 路径 或-cp 路径 //使用-classpath后jvm将不再使用CLASSPATH中的类搜索路径
java调优一般针对 堆内存
堆=年轻代+老年代+持久代
堆设置
-Xms //初始堆大小
-Xmx //最大堆大小
-Xmn //年轻代大小,NewSize与MaxNewSize设为一致
-XX:NewSize=n //年轻代初始大小
-XX:MaxNewSize=n // 年轻代最大大小
-XX:NewRatio=n //设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n //年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:PermSize //设置持久代初始值
-XX:MaxPermSize=n //设置持久代最大值
收集器设置
-XX:+UseSerialGC :设置串行收集器
-XX:+UseParallelGC :设置并行收集器
-XX:+UseParalledlOldGC :设置并行年老代收集器
-XX:+UseConcMarkSweepGC :设置并发收集器
并行收集器设置
-XX:+UseParNewGC //设置年轻代为并行收集
-XX:ParallelGCThreads=n //设置并行收集器的线程数
-XX:MaxGCPauseMillis=n //设置并行收集最大暂停时间
-XX:GCTimeRatio=n //设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:+UseAdaptiveSizePolicy //自动选择年轻代区大小和相应的Survivor区比例
并发收集器设置
-XX:+CMSIncrementalMode //设置为增量模式。适用於单CPU情况。
-XX:ParallelGCThreads=n //设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
CMS收集器(老年代 – 并发GC)
-XX:CMSFullGCsBeforeCompaction=n //多少次后进行内存压缩
-XX:+CMSParallelRemarkEnabled //降低标记停顿
-XX:CMSInitiatingOccupancyFraction=n //使用n%剩余堆时开始CMS收集
垃圾回收统计信息
-XX:+PrintGC //打印GC
-verbose:gc //同-XX:+PrintGC
-XX:+PrintGCDetails //打印GC详细信息
-XX:+PrintGCTimeStamps //打印CG时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps //打印GC时间戳(以日期的形式)
-Xloggc:<filename> //指定GC log的位置,以文件输出
内存溢出时自动产生dump
-XX:+DisableExplicitGC //禁止代码中调用GC,System.gc()会变成一个空调用
-XX:+HeapDumpOnOutOfMemoryError //JVM在出现内存溢出时自动Dump出当前的内存转储快照
-XX:HeapDumpPath=${目录} //生成DUMP文件的路径
-Djava.awt.headless=true
回收机制
年轻代(Young Generation) 年老代(Old Generation) 持久代(Permanent Generation)
年轻代包括(一个Eden区,两个Survivor区:对称没先后关系一个称为(From sqace),一个称为(To Space)。)
- 每次使用Eden和其中一块Survivor
- 大部分对象在Eden区中生成,
- Eden内存不够,就进行Minor GC
- 每次回收时,将Eden和Survivor中还存活着的对象一次性复制到另外一块Survivor空间
- 重复多次(默认15次,最多15次):对象晋身, Survivor中没有被清理的对象就会复制到老年区(Old)
- Survivor对象大于50%也会对象晋身, 复制到老年区(Old)
年老代 在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此年老代中存放的都是一些生命周期较长的对象
持久代 存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响
GC有两种类型:Scavenge GC和Full GC。
Minor GC (Scavenge GC) //清理年轻代
新对象生成,并且在年轻代的Eden区申请空间失败时,就会触发Scavenge GC对Eden区域进行GC,清除非存活对象。不会影响到年老代
Major GC //清理老年代
Full GC //清理新生代,老年代区域,成本较高,会对系统性能产生影响。
对整个堆进行整理,比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:
· 年老代(Tenured)被写满
· 持久代(Perm)被写满
· System.gc()被显示调用
· 上一次GC之后Heap的各域分配策略动态变化
Full GC会触发 STW(stop the word) 程序停止工作
调优:,不让出现Full GC
Jvm监控工具
获取对应进程的线程运行情况, JDK自带一些工具,如Jstack , jmap ,
top –Hp pid
jstack , 输出的线程信息主要包括:jvm自身线程、用户线程等。jvm线程会在jvm启动时就会存在。对于用户线程则是在用户访问时才会生成。
jstack <pid>,用于打印指定Java进程的线程堆栈信息。
jstat –gc 进程号 时间(1000毫秒) 显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间
jmap , 产生dump,打印Java进程的共享对象内存映射或堆内存细节, 各厂商的jvm 手工dump 方法有小区别,如Oracle JVM的6.0版本去掉了-XX:+HeapDumpOnCtrlBreak参数
jmap -histo <pid> 展示class的内存情况
jmap -histo:live <pid> 先触发gc,然后再统计信息
jmap -dump:format=b,file=<filename> <pid> 手动产生dump文件, 将进程的内存heap输出出到filename文件里,
例: 统计25923 进程状况
top -Hp 25923 >top.log
jstack 25923 >./jstack.info
jstat -gcoldcapacity -t 25923 250 3 >gcold.log
jstat –gc 25923 1000 >./gc.log
jmap -dump:format=b,file=dump.bin 25923
Dump文件是Java堆使用情况的内存镜像。主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等
怀疑有内存泄漏的时候就可以制作Dump来查看具体情况
每一个java虚拟机都有及时生成显示所有线程在某一点状态的线程dump的能力
内存dump文件格式:***.hprofdump,配合内存分析工具MAT或与jhat使用,能够以图像的形式直观的展示当前内存是否有问题
JVM中的许多问题都可以使用线程dump文件来进行诊断,其中比较典型的包括线程阻塞,CPU使用率过高,JVM Crash,堆内存不足和类装载等问题。
CPU爆满原因分析:
- 大量IO
- 大量轮询
- FULL GC清理不掉,一直卡在fullgc