JVM基础系列:JVM参数之堆栈空间配置

  JVM中最重要的一部分就是堆空间,基本上大多数的线上JVM问题都是因为堆空间造成的OutOfMemoryError(OOM)。因此掌握JVM关于堆空间的参数配置对于排查线上问题非常重要。

  PS: 本文所有配置,如果没有特殊说明,均是基于JDK1.8。

  堆配置

  我们使用-Xms设置推的初始空间大小,使用-Xms设置堆的最大空间大小。

  java -Xms20m -Xmx30m GCDemo

  上面的命令中,设置JVM堆的初始大小为20M,最大堆空间30M。

  年轻代

  在JDK1.8中,堆分为年轻代和老年代。JVM提供了参数-Xmn来设置年轻代内存的大小,但是没有提供设置老年代大小。但其实老年代大小就等于堆大小减去年轻代大小。

  java -Xms20m -Xmn10m GCDemo

  上面的命令中,我们设置JVM堆初始大小为20M。其中年轻代的大小为10M,那么老年代的大小就是10M了,可以加上XX:+PrintGCDetails 参数来查看内存区域的分配信息,如图所示,老年代大小为10M。

   Eden区

  在年轻代中,分为三个区域:eden、from、to空间。如果要设置这部分的大小,那么需要使用-XX:SurvivorRatio这个参数,该参数设置了eden与from区之间的比例关系。参数设置结果 : -XX:SurvivorRatio = eden/from = eden/to,比如年轻代有10M,而设置-XX:SurvivorRatio参数为2。也就是eden/from = 2,那么可以得出,在新生代为10M的时候,eden区为5M,from、to区各占2.5M。可以运行以下命令验证:

java -Xms20m -Xmn10m -XX:SurvivorRatio:2 -XX:+PrintGCDetails JVMDemo

 

   从上图可以看到,eden占5120k,from和to占2560k。还有一个细节,可以看到PSYoungGen total只有7680k,为什么不是设置的10M?其实是因为total表示的是可用内存,from 区 和 to 区,在同一时间只有一个区域可以使用,另外一个区域使用来minor gc 使复制存活对象的。

  永久代(JDK1.7)

  在JDK1.8之前,所加载的类信息都放在永久代中,可以用+XX:PermSize设置永久代初始大小,用-XX:MaxPermSize设置永久代最大值。

java -XX:PermSize10m -XX:MaxPermSize50m -XX:+PrintGCDetails GCDemo

  元空间(JDK1.8)

  在1.8之前,所有加载的类信息都存放在永久代中,但1.8之后,永久代被移除,取而代之的是元空间(Metaspace)。在元空间这块内存中,有两个参数可以设置:-XX:MetaspaceSize和-XX:MaxMetaspaceSize。

java -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=50m -XX:+PrintGCDetails GCDemo

 

   从执行结果可以看到,Metaspace空间大小大概为26M,并不是设置的10M,那是MetaspaceSize 表示的并非是元空间的大小,它的含义是:主要控制matespaceGC发生的初始阈值,也就是最小阈值。也就是说当使用的matespace空间到达了MetaspaceSize的时候,就会触发Metaspace的GC。MaxMetaspaceSize表示的是保证committed的内存不会超过这个值,一旦超过这个值就会触发GC。MetaspaceSize默认值是20.8M,而MaxMetaspaceSize默认基本是机器的物理内存大小,建议设置一下,如果一直不断膨胀,那么JVM进程可能会被OS kill 掉。

PS:在jvm启动的时候,并不会分配MaxMetaspaceSize这么大的一块内存出来,metaspace是可以一直扩容的,直到到达MaxMetaspaceSize。

  栈空间

  栈空间是每个线程各自占用的一块区域,如果栈空间太小,也会导致StackOverFlow异常,设置栈空间大小,可以使用-Xss参数,设置最大栈空间为2M。

java -Xss2m GCDemo

  直接内存

  在JVM中还有一块内存,它独立于JVM的堆内存,他就是:直接内存。可以使用-XX:MaxDirectMemorySize设置最大内存。如果不设置,默认为醉倒堆空间大小。即-Xmx。  

java -XX:MaxDirectMemorySize=50m GCDemo

  当直接内存使用达到设置值时,就会触发垃圾回收,如果不能有效释放足够空间,就会引发直接内存泄漏导致系统的OOM。

  总结

参数含义
-Xms 初始堆大小
-Xmx 最大堆空间
-Xmn 设置新生代大小
-XX:SurvivorRatio 设置新生代eden空间和from/to空间的比例关系
-XX:PermSize 方法区初始大小
-XX:MaxPermSize 方法区最大大小
-XX:MetaspaceSize 元空间GC阈值(JDK1.8)
-XX:MaxMetaspaceSize 最大元空间大小(JDK1.8)
-Xss 栈大小
-XX:MaxDirectMemorySize 直接内存大小,默认为最大堆空间

 

 

  

posted @ 2022-09-20 18:01  梅晓煜  阅读(2252)  评论(0)    收藏  举报