虚拟机参数
1. JVM 参数
-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
-vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了
1) 堆内存的分配
-Xms JVM 初始分配的堆内存,默认是物理内存的 1/64
-Xmx JVM 最大允许分配的堆内存,按需分配, 默认是物理内存的 1/4
堆内存空余堆内存大于 70% 时,JVM 会减少堆直到 -Xms 的最小限制。因此服务器一般设置-Xms、-Xmx 相等以避免在每次 GC 后调整堆的大小。
2) 新生代内存
-Xmn 设置年轻代的大小
-XX:NewRatio 新生代和老年代的占比
-XX:NewSize 新生代空间
-XX:SurvivorRatio 伊甸园空间和幸存者空间的占比
3) 非堆内存配置(永久代)
-XX:PermSize JVM 初始分配的非堆内存, 默认是物理内存的 1/64
-XX:MaxPermSize JVM 最大允许分配的非堆内存,按需分配, 默认是物理内存的 1/4
4) 为什么会内存益出
a) 这一部分内存用于存放 Class 和 Meta 的信息,Class 在被 Load 的时候被放入 PermGen Space 区域,它和存放 Instance 的 Heap 区域不同。
b)GC(Garbage Collection) 内存回收, 不会在主程序运行期对 PermGen Space 进行清理,所以如果你的 APP 会 LOAD 很多 CLASS 的话,就很可能出现 PermGen space 错误。
这种错误常见在 web 服务器对 JSP 进行 pre compile 的时候。
5) 其他
-Xverify:none 禁止掉字节码验证过程
编译时间是指虚拟机的JIT编译器(Just In Time Compiler)编译热点代码(Hot Spot Code)的耗时。我们知道Java语言为了实现跨平台的特性,Java代码编译出来后形成的Class文件中存储的是字节码(ByteCode),虚拟机通过解释方式执行字节码命令,比起C/C++编译成本地二进制代码来说,速度要慢不少。为了解决程序解释执行的速度问题,JDK 1.2以后,虚拟机内置了两个运行时编译器,如果一段Java方法被调用次数达到一定程度,就会被判定为热代码交给JIT编译器即时编译为本地代码,提高运行速度(这就是HotSpot虚拟机名字的由来)
-Xint 禁止虚拟机编译器运作,强制虚拟机对字节码采用纯解释方式执行。
如果读者想使用这个参数省下Eclipse启动中那2秒的编译时间获得一个“更好看”的成绩的话,那恐怕要失望了,加上这个参数之后,虽然编译时间确实下降到0,但Eclipse启动的总时间剧增到27秒
可以通过以下几个参数要求虚拟机生成GC日志:-XX:+PrintGCTimeStamps(打印GC停顿时间)、-XX:+PrintGCDetails(打印GC详细信息)、-verbose:gc(打印GC信息,输出内容已被前一个参数包括,可以不写)、-Xloggc:gc.log。
虚拟机出现内存溢出时 Dump 出内存堆转存储快照
-XX:+HeapDumpOnOutOfMemoryError
开启 TLAB
-XX:+/-UseTLAB
设置栈内存
-Xss
方法区大小
-XX:PermSize=64M
-XX:MaxPermSize=128M
直接内存区大小
-XX:MaxDirectMemorySize: 直接指定大小, 若不指定则与 Java 堆最大值(-Xmx)一样大
查看类的加载和卸载信息
Product 版本虚拟机使用: -verbose:class、 -XX:+TraceClassLoading
FastDebug 版本虚拟机使用: -XX:+TraceClassUnLoading
GC 优化思路:
避免Young 区域的内存不足,频繁 minigc 导致 GC 次数增加。可以试着调大次区域的内存。
避免 Old 区域的内存,频繁扩容,根据 gc 日志信息,提前确定好 old 区域内存大小
年轻代、老年代,根据场景和业务,调整不同区域的垃圾收集器算法