JVM优化之常用参数解读( -Xss -Xms -Xmx -Xmn)_堆区

JVM区域总体分两类,heap区和非heap区。heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。 非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。

Xmn、Xms、Xmx、Xss都是JVM对内存的配置参数,我们可以根据不同需要区修改这些参数,以达到运行程序的最好效果。

-Xms 堆内存的初始大小,默认为物理内存的1/64

-Xmx 堆内存的最大大小,默认为物理内存的1/4

-Xmn 堆内新生代的大小。通过这个值也可以得到老生代的大小:-Xmx减去-Xmn

-Xss 设置每个线程可使用的内存大小,即栈的大小。在相同物理内存下,减小这个值能生成更多的线程,当然操作系统对一个进程内的线程数还是有限制的,不能无限生成。线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时出现溢出的可能性更大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会出现内存溢出的错误。


建议将Xms和Xmx设为一样的值,避免每次垃圾回收完成后JVM重新分配内存。如果虚拟机启动时设置的Xms比较小,这个时候又需要初始化很多对象,虚拟机会不断地增加内存。配置示例:-Xms1024m -Xmx1024m



-XX:PermSize、-XX:MaxPermSize:分别设置永久代最小大小与最大大小(Java8以前)

-XX:MetaspaceSize、-XX:MaxMetaspaceSize:分别设置元空间最小大小与最大大小(Java8以后)


JVM存储数据的内容的内存分为

  ①堆区(Java堆:所有的线程共享该区域):通过new的方式创建的对象(一个类的实例)、数组所占的空间。

    注意:1)堆区还细分为新生代(Eden空间、From Survivor空间、To Survivor空间)、老年代(Tenured Generation空间)。

              2)Java垃圾回收机制只作用于堆区,对非堆区没有作用。


  ②非堆区:代码、常量、外部访问(比如流在传输数据时所占用的资源)等。


三、常见的参数种类(配置内存)

(1)配置堆区的参数:-Xms、-Xmx、-XX:newSize、-XX:MaxnewSize、-Xmn

(2)配置非堆区的参数:-XX:PermSize、-XX:MaxPermSize


四、堆区参数配置

 (1)-Xms:Java虚拟机堆区内存初始内存分配的大小,按照实际情况进行分配(一般为操作系统可用内存的1/64大小)。

(2)-Xmx:Java虚拟机堆区内存可被分配的最大上限(一般为操作系统可用内存的1/4大小)。

注意:①一般-Xms、-Xmx两个参数会配置相同的值(优点:能够在Java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源)。

(3)-XX:newSize:新生代初始化内存的大小(注意:该值需要小于-Xms的值)。

(4)-XX:MaxnewSize:新生代可被分配的内存的最大上限(注意:该值需要小于-Xmx的值)。

(5)-Xmn:对-XX:newSize、-XX:MaxnewSize两个参数同时进行配置(注意:JDK1.4之后才有该参数)。

五、非堆区参数配置

(1)-XX:PermSize:非堆区初始化内存分配大小。

(2)-XX:MaxPermSize:非堆区分配的内存的最大上限。



大概说JVM的内存组成部分:   堆(Heap)和非堆(Non-heap)内存

按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.""在JVM中堆之外的内存称为非堆内存(Non-heap memory)".可以看出JVM主要管理两种类型的内存:堆和非堆.简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区,JVM内部处理或优化所需的内存(如JIT编译后的代码缓存),每个类结构(如运行时常数池,字段和方法数据)以及方法和构造方法的代码都在非堆内存中.

堆内存分配

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4.默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时, JVM会减少堆直到-Xms的最小限制.因此服务器一般设置-Xms,-Xmx相等以避免在每次GC 后调整堆的大小.

非堆内存分配

JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4.

JVM内存限制(最大值)

首先JVM内存首先受限于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系.简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是 2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了

JVM内存的调优

1. Heap设定与垃圾回收Java Heap分为3个区,Young,Old和Permanent.Young保存刚实例化的对象.当该区被填满时,GC会将对象移到Old区.Permanent区则负责保存反射对象。


常见配置汇总
堆设置

-Xms:初始堆大小 
-Xmx:最大堆大小
-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数.并行收集线程数.

扩展阅读

https://blog.csdn.net/m0_68850571/article/details/123882068
https://blog.csdn.net/qq_27098537/article/details/124436788
https://www.cnblogs.com/lc0605/p/10115651.html
https://blog.csdn.net/xiaozhaoshigedasb/article/details/85480780