不少文章都是讲如何配置JVM各个参数的,可是生产环境里参数的值到底配置为多少,却没有一个具体的指标。文章分四个部分,分别是JVM说明、配置,GC的过程和具体配置值。css
JDK 1.7及之前,Java 类信息、常量池、静态变量都存储在 Perm(永久代)里。类的元数据和静态变量在类加载的时候分配到 Perm,当类被卸载的时候垃圾收集器从 Perm 处理掉。apache
JDK 1.8 的对 JVM 架构的改造将类元数据放到本地内存中,另外,将常量池和静态变量放到 Java 堆里。HotSopt VM 将会为类的元数据明确分配和释放本地内存。在这种架构下,类元信息就突破了原来 -XX:MaxPermSize 的限制,因此PermSize的配置也是无效的,如今可使用更多的本地内存。这样就从必定程度上解决了原来在运行时生成大量类的形成常常 Full GC 问题,如运行时使用反射、代理等bash
干货:能够发现最明显的一个变化是元空间从虚拟机转移到本地内存;默认状况下,元空间的大小仅受本地内存的限制。这意味着之后不会由于永久代空间不够而抛出OOM异常了。
jdk1.8之前版本的class和jar包数据存储在permGen下面 ,permGen大小是固定的,并且项目之间没法共用公有的class,因此很容易碰到OOM异常。
改为metaSpaces后,各个项目会共享一样的class内存空间,好比多个项目都引用了apache-common包,在metaSpaces中只会存储一份apache-common的class,提升了内存的利用率,垃圾回收更有效率。架构
-XX:PermSize=512M -XX:MaxPermSize=1024M
表示在JVM里存储Java类信息,常量池和静态变量的永久代区域初始大小为512M,最大为1024M。在项目启动后,这个值是固定的,若是项目class过多,极可能遇到OutOfMemoryError: PermGen
异常。jvm
-XX:MetaspaceSize=512M XX:MaxMetaspaceSize=1024M
MetaspaceSize若是不作配置,经过jinfo查看默认MetaspaceSize大小(约21M),MaxMetaspaceSize很大很大,前面说过MetaSpace只受本地内存大小限制。工具
jinfo -flag MetaspaceSize 1234 #结果为:-XX:MetaspaceSize=21807104 jinfo -flag MaxMetaspaceSize 1234 #结果为:-XX:MaxMetaspaceSize=18446744073709547520
干货:MetaspaceSize为出发FullGC的阈值,默认约为21M,如作了配置,最小阈值为自定义配置大小。空间使用达到阈值,触发FullGC,同时对该值扩大。固然若是元空间实际使用小于阈值,在GC的时候也会对该值缩小。
MaxMetaspaceSize为元空间的最大值,若是设置过小,可能会致使频繁FullGC,甚至OOM。spa
首先贴一张网上盗来的大图,用它来讲明下GC的过程再合适不过。代理
清理Eden区和Survivor区叫Minor GC;清理Old区叫Major GC;清理整个堆空间—包括年轻代和老年代叫Full GC。code
前面三个部分对JVM进行了总体的了解,接下来是本文的重点。orm
-XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256M -Xms256m -Xmx256m
文章看下来上面这段配置的意思很简单,设置元空间的初始值和最大值,设置堆空间的初始值和最大值。
为何MetaspaceSize要设置为128M?为何堆内存初始值Xms设置为256M而不是512M?
按照Java官方的指导
可让系统运行一段时间后查看系统的各个指标,而后在进行配置。以下用jstat工具查看jvm的状况
jstat -gc 12345 ### S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT 13824.0 22528.0 13377.0 0.0 548864.0 535257.2 113152.0 46189.3 73984.0 71119.8 9728.0 9196.2 14 0.259 3 0.287 0.546
OU表示老年代所占用的内存为 46189.3 K(大约45M);那么jvm相应的配置参数应该作以下修改
-XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M -Xms180m -Xmx180m