zoukankan      html  css  js  c++  java
  • JVM虚拟机选项:Xms Xmx PermSize MaxPermSize区别(转)

    java启动参数共分为三类

    其一是标准参数( -),所有的JVM实现都必须实现这些参数的功能,而且向后兼容

    其二是非标准参数( -X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容

    其三是非Stable参数( -XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用



    java虽然是自动回收内存,但是应用程序,尤其服务器程序最好根据业务情况指明内存分配限制。
    否则可能导致应用程序宕掉。

    举例说明含义:
    -Xms128m
    表示JVM Heap(堆内存)最小尺寸128MB,初始分配
    -Xmx512m
    表示JVM Heap(堆内存)最大允许的尺寸256MB,按需分配。

    说明:如果-Xmx不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误。

    IDEA中配置 -Xms  -Xmx 示例:




    PermSize和MaxPermSize指明虚拟机为java永久生成对象(Permanate generation)
    如,class对象、方法对象这些可反射(reflective)对象分配内存限制,这些内存不包括在Heap(堆内存)区之中。

    -XX:PermSize=64MB 最小尺寸,初始分配
    -XX:MaxPermSize=256MB 最大允许分配尺寸,按需分配
    过小会导致:java.lang.OutOfMemoryError: PermGen space

    MaxPermSize缺省值和-server -client选项相关。
    -server选项下默认MaxPermSize为64m
    -client选项下默认MaxPermSize为32m


    经验:
    1、慎用最小限制选项Xms,PermSize已节约系统资源。

    =========================================================

    近期研究对jvm的内存使用情况进行监控,因此对观察虚拟机的内存使用方法做了一些收集,对jvm的参数设置了解了一下:

    几个基本概念:

    PermGen space:全称是Permanent Generation space,即永久代。就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域,GC(Garbage Collection)应该不会对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。
    Heap space:存放Instance。Java Heap分为3个区,Young即新生代,Old即老生代和Permanent。Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象。

    几个参数设置的意义:

    xms/xmx:定义YOUNG+OLD段的总尺寸
    ms为JVM启动时YOUNG+OLD的内存大小
    mx为最大可占用的YOUNG+OLD内存大小。
    在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销


    NewSize/MaxNewSize:定义YOUNG段的尺寸,
    NewSize为JVM启动时YOUNG的内存大小;
    MaxNewSize为最大可占用的YOUNG内存大小。

    在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。
    PermSize/MaxPermSize:定义Perm段的尺寸,PermSize为JVM启动时Perm的内存大小;MaxPermSize为最大可占用的Perm内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。
    SurvivorRatio:设置YOUNG代中Survivor空间和Eden空间的比例

    申请一块内存的过程:

    A. JVM会试图为相关Java对象在Eden中初始化一块内存区域
    B. 当Eden空间足够时,内存申请结束。否则到下一步
    C. JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收);释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区/OLD区
    D. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区
    E. 当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级)
    F. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”

    我们的一种resin服务器的jvm参数设置:

    “-Xmx2000M -Xms2000M -Xmn500M -XX:PermSize=250M -XX:MaxPermSize=250M -Xss256K -XX:+DisableExplicitGC -XX:SurvivorRatio=1 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:LargePageSizeInBytes=128M -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=60 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log”

     是一种典型的响应时间优先型的配置。

    Java中有四种不同的回收算法,对应的启动参数为
    –XX:+UseSerialGC
    –XX:+UseParallelGC
    –XX:+UseParallelOldGC
    –XX:+UseConcMarkSweepGC

    1. Serial Collector
    大部分平台或者强制 java -client 默认会使用这种。
    young generation算法 = serial
    old generation算法 = serial (mark-sweep-compact)
    这种方法的缺点很明显,stop-the-world, 速度慢。服务器应用不推荐使用。

    2. Parallel Collector
    在linux x64上默认是这种,其他平台要加 java -server 参数才会默认选用这种。
    young = parallel,多个thread同时copy
    old = mark-sweep-compact = 1
    优点:新生代回收更快。因为系统大部分时间做的gc都是新生代的,这样提高了throughput(cpu用于非gc时间)
    缺点:当运行在8G/16G server上old generation live object太多时候pause time过长

    3. Parallel Compact Collector (ParallelOld)
    young = parallel = 2
    old = parallel,分成多个独立的单元,如果单元中live object少则回收,多则跳过
    优点:old old generation上性能较 parallel 方式有提高
    缺点:大部分server系统old generation内存占用会达到60%-80%, 没有那么多理想的单元live object很少方便迅速回收,同时compact方面开销比起parallel并没明显减少。

    4. Concurent Mark-Sweep(CMS) Collector
    young generation = parallel collector = 2
    old = cms
    同时不做 compact 操作。
    优点:pause time会降低, pause敏感但CPU有空闲的场景需要建议使用策略4.
    缺点:cpu占用过多,cpu密集型服务器不适合。另外碎片太多,每个object的存储都要通过链表连续跳n个地方,空间浪费问题也会增大。

     内存监控的方法:

    1.  jmap -heap pid
            查看java 堆(heap)使用情况
     
            using thread-local object allocation.
            Parallel GC with 4 thread(s)          //GC 方式

             Heap Configuration:       //堆内存初始化配置
             MinHeapFreeRatio=40     //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
             MaxHeapFreeRatio=70  //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
             MaxHeapSize=512.0MB  //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
             NewSize  = 1.0MB          //对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
             MaxNewSize =4095MB   //对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
             OldSize  = 4.0MB            //对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小
             NewRatio  = 8         //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
             SurvivorRatio = 8    //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
              PermSize= 16.0MB       //对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小
              MaxPermSize=64.0MB  //对应jvm启动参数-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小
     
     
              Heap Usage:               //堆内存分步
              PS Young Generation
              Eden Space:          //Eden区内存分布
                capacity = 20381696 (19.4375MB)  //Eden区总容量
                used     = 20370032 (19.426376342773438MB)  //Eden区已使用
                free     = 11664 (0.0111236572265625MB)  //Eden区剩余容量
                99.94277218147106% used  //Eden区使用比率
             From Space:        //其中一个Survivor区的内存分布
                 capacity = 8519680 (8.125MB)
                 used     = 32768 (0.03125MB)
                 free     = 8486912 (8.09375MB)
                 0.38461538461538464% used
            To Space:            //另一个Survivor区的内存分布
                capacity = 9306112 (8.875MB)
                used     = 0 (0.0MB)
                free     = 9306112 (8.875MB)
                0.0% used
            PS Old Generation  //当前的Old区内存分布
                capacity = 366280704 (349.3125MB)
                used     = 322179848 (307.25464630126953MB)
                free     = 44100856 (42.05785369873047MB)
                87.95982001825573% used
            PS Perm Generation  //当前的 “永生代” 内存分布
                capacity = 3

     http://blog.sina.com.cn/s/blog_684fe8af0100v4mt.html

    调试参数

    打印启动参数

    可以查看默认参数

    1. java -XX:+PrintCommandLineFlags-version

    打印GC日志

    不要用 XX:+UseGCLogFileRotation,这个会丢失旧的日志文件,而且重启会覆盖当前日志文件:

    1. -XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:/home/GCEASY/gc.log -XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=5-XX:GCLogFileSize=20M

    应该用下面这个

    1. -XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:/home/GCEASY/gc-%t.log

    打印ClassLoader日志

    这个参数会在控制台打印所有类加载/卸载信息

    1. -XX:+TraceClassLoading-XX:+TraceClassUnloading

    OOM时Dump内存

    1. -XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/crashes/my-heap-dump.hprof

    OOM时执行脚本(比如重启)

    1. -XX:OnOutOfMemoryError=/scripts/restart-myapp.sh

    打印JIT时间

    1. -XX:-CITime

    方法被编译时打印相关信息

    1. -XX:-PrintCompilation

    JMX

    1. -Djava.net.preferIPv4Stack=true

    2. -Dcom.sun.management.jmxremote

    3. -Djava.rmi.server.hostname={hostname}

    4. -Dcom.sun.management.jmxremote.port={port}

    5. -Dcom.sun.management.jmxremote.authenticate=false

    内存类

    JVM设置内存的单位默认是字节(不加单位的情况下)。

    也可以在大小后面增加单位,例如:

    1. -Xmn256m

    2. -Xmn262144k

    3. -Xmn268435456

    设置初始新生代大小

    1. -XX:NewSize=2G(也可以是2M)

    设置最大新生代大小

    1. -XX:MaxNewSize=2G(也可以是2M)

    注意:-Xmn优先级大于-XX:NewRatio

    设置Eden/Survivor比例

    表示两个Survivor和Edgen区的比,8表示两个Survivor:Eden=2:8,即一个Survivor占新生代的1/10。

    计算方式为:

    1. SurvivorSize(1) = YoungGenerationSize/ (2+<SurvivorRatio)

    2. EdenSize= YoungGenerationSize/ (2+SurvivorRatio) * SurvivorRatio

    配置:

    1. -XX:SurvivorRatio=8

    8也是默认的比例,不过这个比例在Parallel Scavenge(新生代并行回收器,JDK5以后的默认新生代回收器)回收器下是动态的,运行时会出现Eden/Survivor比例和配置的不同。整编:微信公众号,搜云库技术团队,ID:souyunku

    由于与吞吐量关系密切,Parallel Scavenge收集器也经常称为“吞吐量优先”收集器。除上述两个参数之外,Parallel Scavenge收集器还有一个参数-XX:+UseAdaptiveSizePolicy值得关注。这是一个开关参数,当这个参数打开之后,就不需要手工指定新生代的大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种调节方式称为GC自适应的调节策略(GC Ergonomics)[插图]。如果读者对于收集器运作原来不太了解,手工优化存在困难的时候,使用Parallel Scavenge收集器配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成将是一个不错的选择。只需要把基本的内存数据设置好(如-Xmx设置最大堆),然后使用MaxGCPauseMillis参数(更关注最大停顿时间)或GCTimeRatio (更关注吞吐量)参数给虚拟机设立一个优化目标,那具体细节参数的调节工作就由虚拟机完成了。自适应调节策略也是Parallel Scavenge收集器与ParNew收集器的一个重要区别。

    https://docs.oracle.com/javas...

    设置老年代大小

    老年代大小无法直接设置,只能通过堆大小+分配比例进行调整

    1. #设置新老一代大小之间的比率。默认值为2。2表示New Size:Old Size=1:2,则新生代占堆大小的1/3,老年代占堆大小的2/3

    2. -XX:NewRatio=2

    新生代老年代大小计算方式为:

    1. NewSize= HeapSize/ NewRatio+ 1

    2. OldSize= (HeapSize/ NewRatio+ 1) * NewRatio

    设置永久代(PermGen/MetaSpace)大小

    1. #设置分配给永久生成的空间,如果超出该空间,则会触发垃圾回收。此选项在JDK 8中已弃用,并由-XX:MetaspaceSize选项取代。

    2. -XX:PermSize=size

    3. #设置最大永久生成空间大小(以字节为单位)。此选项在JDK 8中已弃用,并由-XX:MaxMetaspaceSize选项取代。

    4. -XX:MaxPermSize=size

    5. #设置分配的Metaspace的大小,Metaspace将在首次超过垃圾收集时触发垃圾收集。垃圾收集的阈值取决于使用的元数据量而增加或减少。默认大小取决于平台。

    6. -XX:MetaspaceSize=size

    7. #设置可以分配给Metaspace的最大本机内存。默认情况下,大小不受限制。应用程序的Metaspace量取决于应用程序本身,其他正在运行的应用程序以及系统上可用的内存量

    8. -XX:MaxMetaspaceSize=size

    初始大小和最大值的区别

    初始值(比如 -Xms)为JVM启动是向操作系统申请的内存大小( malloc),最大值(比如 -Xmx)表示,当使用的内存超过初始值后扩容的最大值

    PS: JVM配置了多少内存并不是说启动后就会占用多少物理内存,因为操作系统的内存分配是惰性的。对于已申请的内存虽然会分配地址空间,但并不会直接占用物理内存,真正使用的时候才会映射到实际的物理内存。

    GC类

    这里说一下PermGen/Metaspace的GC,没有查到官方资料说永久代的固定垃圾回收器,但是在stackoverflow上有人回答到:

    所有垃圾回收器都会回收永久代,包括PS/CMS,但并不是每个GC周期都会清理永久代。

    这个不用纠结,看GC日志里清理的信息即可。

    Serial/Serial Old

    最古老的,单线程,独占式,成熟,每次GC会STW,适合单CPU 服务器

    Serial是一个新生代收集器,Serial Old是Serial收集器的的老年代版本

    新生代和老年代都用串行收集器

    1. -XX:+UseSerialGC

    新生代使用ParallerGC,老年代使用Serial Old

    1. -XX:+UseParallelGC

    ParNew

    和Serial基本没区别,唯一的区别:多线程,多CPU的,停顿时间比Serial少

    新生代使用ParNew,老年代使用Serial Old

    1. -XX:+UseParNewGC(在Java8中已弃用,在Java9中已删除)

    Parallel Scavenge(ParallerGC)/Parallel Old

    关注吞吐量的垃圾收集器,高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。整编:微信公众号,搜云库技术团队,ID:souyunku

    所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。

    Parallel Scavenge是一个新生代收集器,Parallel Old是Parallel Scavenge收集器的的老年代版本

    新生代使用ParallerGC,老年代使用Parallel Old

    1. -XX:+UseParallelGC

    2. #等价于

    3. -XX:+UseParallelOldGC

    Concurrent Mark Sweep (CMS)

    CMS(Concurrent Mark Sweep),收集器是一种以获取最短回收停顿时间为目标的收集器,一个老年代垃圾回收器。目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。

    新生代使用ParNew,老年代的用CMS

    1. -XX:+UseConcMarkSweepGC

    G1

    使用G1收集器

    1. -XX:+UseG1GC

    垃圾回收器的组合

    下面是一些缺省的写法

    JDK7

    1. JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "

    2. JAVA_DEBUG_OPTS=" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/GCEASY/gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof -XX:OnOutOfMemoryError=/scripts/restart-myapp.sh "

    JDK8

    1. JAVA_MEM_OPTS=" -server -Xmx2g -Xms2g -Xmn256m -XX:MetaspaceSize=256m -Xss1024m -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 "

    2. JAVA_DEBUG_OPTS=" -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/GCEASY/gc-%t.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof -XX:OnOutOfMemoryError=/scripts/restart-myapp.sh "

    关于G1,虽然说JDK8中已经支持G1了,但是并不是说一定需要。

    G1的重要特点是为用户的应用程序的提供一个低GC延时和大内存GC的解决方案,适用于大内存场景(官方推荐堆6G以上)

    如果程序正在使用CMS或ParallelOld垃圾回收器,并且具有一个或多个以下特征,那么则可以考虑升级为G1:

    • Full GC持续时间太长或太频繁

    • 对象分配率或年轻代升级老年代很频繁

    • 垃圾收集时间或压缩暂停(超过0.5至1秒)时间过长

    PS:如果正在使用CMS或ParallelOld收集器,并且程序没有遇到长时间的垃圾收集暂停,那么就不需要升级到G1

    作者:空无

    来源:http://suo.im/5Y8mTF

  • 相关阅读:
    PAT 甲级 1132 Cut Integer (20 分)
    AcWing 7.混合背包问题
    AcWing 9. 分组背包问题
    AcWing 5. 多重背包问题 II
    AcWing 3. 完全背包问题
    AcWing 4. 多重背包问题
    AcWing 2. 01背包问题
    AcWing 875. 快速幂
    AcWing 874. 筛法求欧拉函数
    AcWing 873. 欧拉函数
  • 原文地址:https://www.cnblogs.com/softidea/p/4043804.html
Copyright © 2011-2022 走看看