精华内容
下载资源
问答
  • JVM堆内存非堆内存(heap)官方详解

    千次阅读 2019-04-02 14:48:10
    JVM堆内存非堆内存(heap)官方详解 JAVA堆内存管理是影响性能主要因素之一。 堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的。 先看下JAVA堆内存是如何划分的,如图:...

    JVM堆内存与非堆内存(heap)官方详解
    JAVA堆内存管理是影响性能主要因素之一。
    堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作的。

    先看下JAVA堆内存是如何划分的,如图:

    Java堆内存又溢出了!教你一招必杀技

    JVM内存划分为堆内存和非堆内存,堆内存分为年轻代(Young Generation)、老年代(Old Generation),非堆内存就一个永久代(Permanent Generation)。
    年轻代又分为Eden和Survivor区。Survivor区由FromSpace和ToSpace组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1。
    堆内存用途:存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收。
    非堆内存用途:永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据、方法、常量、属性等。
    在JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存。
    元空间有注意有两个参数:

    MetaspaceSize :初始化元空间大小,控制发生GC阈值
    MaxMetaspaceSize : 限制元空间大小上限,防止异常占用过多物理内存
    为什么移除永久代?
    移除永久代原因:为融合HotSpot JVM与JRockit VM(新JVM技术)而做出的改变,因为JRockit没有永久代。
    有了元空间就不再会出现永久代OOM问题了!

    分代概念
    新生成的对象首先放到年轻代Eden区,当Eden空间满了,触发Minor GC,存活下来的对象移动到Survivor0区,Survivor0区满后触发执行Minor GC,Survivor0区存活对象移动到Suvivor1区,这样保证了一段时间内总有一个survivor区为空。经过多次Minor GC仍然存活的对象移动到老年代。
    老年代存储长期存活的对象,占满时会触发Major GC=Full GC,GC期间会停止所有线程等待GC完成,所以对响应要求高的应用尽量减少发生Major GC,避免响应超时。
    Minor GC : 清理年轻代
    Major GC : 清理老年代
    Full GC : 清理整个堆空间,包括年轻代和永久代
    所有GC都会停止应用所有线程。

    为什么分代?
    将对象根据存活概率进行分类,对存活时间长的对象,放到固定区,从而减少扫描垃圾时间及GC频率。针对分类进行不同的垃圾回收算法,对算法扬长避短。

    为什么survivor分为两块相等大小的幸存空间?
    主要为了解决碎片化。如果内存碎片化严重,也就是两个对象占用不连续的内存,已有的连续内存不够新对象存放,就会触发GC。

    JVM堆内存常用参数
    参数 描述
    -Xms 堆内存初始大小,单位m、g
    -Xmx(MaxHeapSize) 堆内存最大允许大小,一般不要大于物理内存的80%
    -XX:PermSize 非堆内存初始大小,一般应用设置初始化200m,最大1024m就够了
    -XX:MaxPermSize 非堆内存最大允许大小
    -XX:NewSize(-Xns) 年轻代内存初始大小
    -XX:MaxNewSize(-Xmn) 年轻代内存最大允许大小,也可以缩写
    -XX:SurvivorRatio=8 年轻代中Eden区与Survivor区的容量比例值,默认为8,即8:1
    -Xss 堆栈内存大小
    垃圾回收算法(GC,Garbage Collection)
    红色是标记的非活动对象,绿色是活动对象。

    标记-清除(Mark-Sweep)
    GC分为两个阶段,标记和清除。首先标记所有可回收的对象,在标记完成后统一回收所有被标记的对象。同时会产生不连续的内存碎片。碎片过多会导致以后程序运行时需要分配较大对象时,无法找到足够的连续内存,而不得已再次触发GC。
    Java堆内存又溢出了!教你一招必杀技

    复制(Copy)
    将内存按容量划分为两块,每次只使用其中一块。当这一块内存用完了,就将存活的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。这样使得每次都是对半个内存区回收,也不用考虑内存碎片问题,简单高效。缺点需要两倍的内存空间。
    Java堆内存又溢出了!教你一招必杀技

    标记-整理(Mark-Compact)
    也分为两个阶段,首先标记可回收的对象,再将存活的对象都向一端移动,然后清理掉边界以外的内存。此方法避免标记-清除算法的碎片问题,同时也避免了复制算法的空间问题。
    一般年轻代中执行GC后,会有少量的对象存活,就会选用复制算法,只要付出少量的存活对象复制成本就可以完成收集。而老年代中因为对象存活率高,没有额外过多内存空间分配,就需要使用标记-清理或者标记-整理算法来进行回收。
    Java堆内存又溢出了!教你一招必杀技

    垃圾收集器
    串行收集器(Serial)
    比较老的收集器,单线程。收集时,必须暂停应用的工作线程,直到收集结束。
    并行收集器(Parallel)
    多条垃圾收集线程并行工作,在多核CPU下效率更高,应用线程仍然处于等待状态。
    CMS收集器(Concurrent Mark Sweep)
    CMS收集器是缩短暂停应用时间为目标而设计的,是基于标记-清除算法实现,整个过程分为4个步骤,包括:
    初始标记(Initial Mark)
    并发标记(Concurrent Mark)
    重新标记(Remark)
    并发清除(Concurrent Sweep)
    其中,初始标记、重新标记这两个步骤仍然需要暂停应用线程。初始标记只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段是标记可回收对象,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作导致标记产生变动的那一部分对象的标记记录,这个阶段暂停时间比初始标记阶段稍长一点,但远比并发标记时间段。
    由于整个过程中消耗最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,CMS收集器内存回收与用户一起并发执行的,大大减少了暂停时间。

    G1收集器(Garbage First)
    G1收集器将堆内存划分多个大小相等的独立区域(Region),并且能预测暂停时间,能预测原因它能避免对整个堆进行全区收集。G1跟踪各个Region里的垃圾堆积价值大小(所获得空间大小以及回收所需时间),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region,从而保证了再有限时间内获得更高的收集效率。
    G1收集器工作工程分为4个步骤,包括:
    初始标记(Initial Mark)
    并发标记(Concurrent Mark)
    最终标记(Final Mark)
    筛选回收(Live Data Counting and Evacuation)
    初始标记与CMS一样,标记一下GC Roots能直接关联到的对象。并发标记从GC Root开始标记存活对象,这个阶段耗时比较长,但也可以与应用线程并发执行。而最终标记也是为了修正在并发标记期间因用户程序继续运作而导致标记产生变化的那一部分标记记录。最后在筛选回收阶段对各个Region回收价值和成本进行排序,根据用户所期望的GC暂停时间来执行回收。

    垃圾收集器参数
    参数 描述
    -XX:+UseSerialGC 串行收集器
    -XX:+UseParallelGC 并行收集器
    -XX:+UseParallelGCThreads=8 并行收集器线程数,同时有多少个线程进行垃圾回收,一般与CPU数量相等
    -XX:+UseParallelOldGC 指定老年代为并行收集
    -XX:+UseConcMarkSweepGC CMS收集器(并发收集器)
    -XX:+UseCMSCompactAtFullCollection 开启内存空间压缩和整理,防止过多内存碎片
    -XX:CMSFullGCsBeforeCompaction=0 表示多少次Full GC后开始压缩和整理,0表示每次Full GC后立即执行压缩和整理
    -XX:CMSInitiatingOccupancyFraction=80% 表示老年代内存空间使用80%时开始执行CMS收集,防止过多的Full GC
    -XX:+UseG1GC G1收集器
    -XX:MaxTenuringThreshold=0 在年轻代经过几次GC后还存活,就进入老年代,0表示直接进入老年代
    为什么会堆内存溢出?
    在年轻代中经过GC后还存活的对象会被复制到老年代中。当老年代空间不足时,JVM会对老年代进行完全的垃圾回收(Full GC)。如果GC后,还是无法存放从Survivor区复制过来的对象,就会出现OOM(Out of Memory)。

    OOM(Out of Memory)异常常见有以下几个原因:
    1)老年代内存不足:java.lang.OutOfMemoryError:Javaheapspace
    2)永久代内存不足:java.lang.OutOfMemoryError:PermGenspace
    3)代码bug,占用内存无法及时回收。
    OOM在这几个内存区都有可能出现,实际遇到OOM时,能根据异常信息定位到哪个区的内存溢出。
    可以通过添加个参数-XX:+HeapDumpOnOutMemoryError,让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后分析。

    熟悉了JAVA内存管理机制及配置参数,下面是对JAVA应用启动选项调优配置:

    JAVA_OPTS="-server -Xms512m -Xmx2g -XX:+UseG1GC -XX:SurvivorRatio=6 -XX:MaxGCPauseMillis=400 -XX:G1ReservePercent=15 -XX:ParallelGCThreads=4 -XX:
    ConcGCThreads=1 -XX:InitiatingHeapOccupancyPercent=40 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:…/logs/gc.log"
    设置堆内存最小和最大值,最大值参考历史利用率设置
    设置GC垃圾收集器为G1
    启用GC日志,方便后期分析
    小结
    选择高效的GC算法,可有效减少停止应用线程时间。
    频繁Full GC会增加暂停时间和CPU使用率,可以加大老年代空间大小降低Full GC,但会增加回收时间,根据业务适当取舍。

    展开全文
  • jvm堆内存非堆内存(转载)

    千次阅读 2019-03-27 15:46:17
    堆和非堆内存 按照官方的说法:“Java 虚拟机具有一个堆(Heap),堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap ...

    堆和非堆内存

     

    按照官方的说法:“Java 虚拟机具有一个堆(Heap),堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。

     

    JVM主要管理两种类型的内存:堆和非堆。

     

    Heap memory Code Cache

    Eden Space

    Survivor Space

    Tenured Gen

    non-heap memory Perm Gen

    native heap?(I guess)

     

    堆内存

     

    Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。

     

    堆的大小可以固定,也可以扩大和缩小。堆的内存不需要是连续空间。

     

    非堆内存

     

    Java 虚拟机管理堆之外的内存(称为非堆内存)。

     

    Java 虚拟机具有一个由所有线程共享的方法区。方法区属于非堆内存。它存储每个类结构,如运行时常数池、字段和方法数据,以及方法和构造方法的代码。它是在 Java 虚拟机启动时创建的。

     

    方法区在逻辑上属于堆,但 Java 虚拟机实现可以选择不对其进行回收或压缩。与堆类似,方法区的大小可以固定,也可以扩大和缩小。方法区的内存不需要是连续空间。

     

    除了方法区外,Java 虚拟机实现可能需要用于内部处理或优化的内存,这种内存也是非堆内存。例如,JIT 编译器需要内存来存储从 Java 虚拟机代码转换而来的本机代码,从而获得高性能。

     

    几个基本概念

     

    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区则负责保存反射对象。

     

    堆内存分配

     

    • JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;

    • JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。

    • 默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;

    • 空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。

    • 因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。

    • 说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,无法用try…catch捕捉。

     

    非堆内存分配

     

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

    2. 由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

     

    • 还有一说:MaxPermSize缺省值和-server -client选项相关,-server选项下默认MaxPermSize为64m,-client选项下默认MaxPermSize为32m。这个我没有实验。

     

    3. XX:MaxPermSize设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存益出。

    4. 为什么会内存益出:

     

    • 这一部分内存用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance的Heap区域不同。

    • GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,就很可能出现PermGen space错误。

     

    5. 这种错误常见在web服务器对JSP进行pre compile的时候。

     

    JVM内存限制(最大值)

     

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

     

    2. 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动?

     

    通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操作系统。所以说设置VM参数导致程序无法启动主要有以下几种原因:

     

    • 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;

    • -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。说到实际物理内存这里需要说明一点的是,如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了。

     

    3. 如果你有一个双核的CPU,也许可以尝试这个参数: -XX:+UseParallelGC 让GC可以更快的执行。(只是JDK 5里对GC新增加的参数)

     

    4. 如果你的WEB APP下都用了大量的第三方jar,其大小超过了服务器jvm默认的大小,那么就会产生内存益出问题了。解决方法: 设置MaxPermSize大小。

     

    • 增加服务器启动的JVM参数设置: -Xms128m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

    • 如tomcat,修改TOMCAT_HOME/bin/catalina.sh,在echo “Using CATALINA_BASE: $CATALINA_BASE”上面加入以下行:JAVA_OPTS=”-server -XX:PermSize=64M -XX:MaxPermSize=128m

     

    5. 建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以减少jar 文档重复占用内存

     

    JVM内存设置参数

     

    • 内存设置参数

     

     

    • 说明:

    1. 如果-Xmx不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM不是Throwable的,无法用try…catch捕捉。

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

    3. -XX:MaxPermSize分配过小会导致:java.lang.OutOfMemoryError: PermGen space。

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

     

    • 申请一块内存的过程

     

    1. JVM会试图为相关Java对象在Eden中初始化一块内存区域

    2. 当Eden空间足够时,内存申请结束。否则到下一步

    3. JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收);释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区/OLD区

    4. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区

    5. 当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级)

    6. 完全垃圾收集后,若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

     

    Serial Collector

     

    大部分平台或者强制 java -client 默认会使用这种。

     

    young generation算法 = serial

    old generation算法 = serial (mark-sweep-compact)

     

    这种方法的缺点很明显, stop-the-world, 速度慢。服务器应用不推荐使用。

     

    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过长

     

    Parallel Compact Collector (ParallelOld)

     

    young = parallel = 2

     

    old = parallel,分成多个独立的单元,如果单元中live object少则回收,多则跳过

     

    优点:old old generation上性能较 parallel 方式有提高

     

    缺点:大部分server系统old generation内存占用会达到60%-80%, 没有那么多理想的单元live object很少方便迅速回收,同时compact方面开销比起parallel并没明显减少。

     

    Concurrent Mark-Sweep(CMS) Collector

     

    young generation = parallel collector = 2

    old = cms

     

    同时不做 compact 操作。

     

    优点:pause time会降低, pause敏感但CPU有空闲的场景需要建议使用策略4.

     

    缺点:cpu占用过多,cpu密集型服务器不适合。另外碎片太多,每个object的存储都要通过链表连续跳n个地方,空间浪费问题也会增大。

     

    内存监控方法

     

    • jmap -heap 查看java 堆(heap)使用情况

     

    jmap -heap pid 

      

    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 = 32243712 (30.75MB)

    used     = 28918584 (27.57891082763672MB)

    free     = 3325128 (3.1710891723632812MB)

    89.68751488662348% used

     

    • JVM内存监控工具

     

    <%@ page import="java.lang.management.*" %>

    <%@ page import="java.util.*" %>

    <html>

    <head>

      <title>JVM Memory Monitor</title>

    </head>

    <body>

    <table border="0" width="100%">

        <tr><td colspan="2" align="center"><h3>Memory MXBean</h3></td></tr>

        <tr><td width="200">Heap Memory Usage</td><td><%=ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()%></td></tr>

        <tr><td>Non-Heap Memory Usage</td><td><%=ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()%></td></tr>

        <tr><td colspan="2"> </td></tr>

        <tr><td colspan="2" align="center"><h3>Memory Pool MXBeans</h3></td></tr>

    <%

            Iterator iter = ManagementFactory.getMemoryPoolMXBeans().iterator();

            while (iter.hasNext()) {

                MemoryPoolMXBean item = (MemoryPoolMXBean) iter.next();

    %>

    <tr><td colspan="2">

        <table border="0" width="100%" style="border: 1px #98AAB1 solid;">

            <tr><td colspan="2" align="center"><b><%= item.getName() %></b></td></tr>

            <tr><td width="200">Type</td><td><%= item.getType() %></td></tr>

            <tr><td>Usage</td><td><%= item.getUsage() %></td></tr>

            <tr><td>Peak Usage</td><td><%= item.getPeakUsage() %></td></tr>

            <tr><td>Collection Usage</td><td><%= item.getCollectionUsage() %></td></tr>

        </table>

    </td></tr>

    <tr><td colspan="2"> </td></tr>

    <%} %>

    </table>

    </body>

    </html>

    推荐一个交流学习群:650385180里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多:

    转载地址:https://www.cnblogs.com/lfs2640666960/p/8516916.html

    展开全文
  • Java堆内存Heap与非堆内存Non-Heap概要

    千次阅读 2017-10-20 10:16:28
    而又可以粗略分为堆内存非堆内存。一般程序员最关心的也是堆内存。也是最容易造成内存泄漏的一部分内存,也是jvm垃圾回收时主要操作的内存空间。堆内存又可以分为新生代、年老代、永久代,具体垃圾回收机制查看另...


         JAVA虚拟机内存结构分为以下5部分:程序计数器,虚拟机栈,本地方法栈,方法区,堆。具体可查看上一篇文章JAVA虚拟机内存分配概要。而又可以粗略分为堆内存和非堆内存。一般程序员最关心的也是堆内存。也是最容易造成内存泄漏的一部分内存,也是jvm垃圾回收时主要操作的内存空间。堆内存又可以分为新生代、年老代、永久代,具体垃圾回收机制查看另一篇文章Java虚拟机:Java垃圾回收(GC)机制详解


    堆(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以上的处理器就不会有限制了。

    程序运行时可以通过jconsole查看堆内存和非堆内存运行情况


    展开全文
  • -XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配 我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义。 1)堆(Heap)和堆(Non-heap)内存  按照官方的说法:“Java 虚拟机...

    Eclipse崩溃,错误提示:
    MyEclipse has detected that less than 5% of the 64MB of Perm 
    Gen (Non-heap memory) space remains. It is strongly recommended
    that you exit and restart MyEclipse with new virtual machine memory
    paramters to increase this memory.   Failure to do so can result in
    data loss. The recommended Eclipse memory parameters are: 
    eclipse.exe -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
     
    1.参数的含义
    -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
    -vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了
    -Xms128m JVM初始分配的堆内存
    -Xmx512m JVM最大允许分配的堆内存,按需分配
    -XX:PermSize=64M JVM初始分配的非堆内存
    -XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配

    我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义。


    1)堆(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 后调整堆的大小。
     说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,无法用try...catch捕捉。 


    非堆内存分配


     JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。(还有一说:MaxPermSize缺省值和-server -client选项相关,
     -server选项下默认MaxPermSize为64m,-client选项下默认MaxPermSize为32m。这个我没有实验。)
     上面错误信息中的PermGen space的全称是Permanent Generation space,是指内存的永久保存区域。还没有弄明白PermGen space是属于非堆内存,还是就是非堆内存,但至少是属于了。
    XX:MaxPermSize设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存益出。 
    说说为什么会内存益出: 
    (1)这一部分内存用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance的Heap区域不同。 
    (2)GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,就很可能出现PermGen space错误。
      这种错误常见在web服务器对JSP进行pre compile的时候。  


    2)JVM内存限制(最大值)


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

    2. 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动?
     通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操作系统。所以说设置VM参数导致程序无法启动主要有以下几种原因:
    1) 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;
    2) -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。说到实际物理内存这里需要说明一点的是,
     如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了。

    3. 为何将上面的参数写入到eclipse.ini文件Eclipse没有执行对应的设置?
     那为什么同样的参数在快捷方式或者命令行中有效而在eclipse.ini文件中是无效的呢?这是因为我们没有遵守eclipse.ini文件的设置规则:
    参数形如“项 值”这种形式,中间有空格的需要换行书写,如果值中有空格的需要用双引号包括起来。比如我们使用-vm C:/Java/jre1.6.0/bin/javaw.exe参数设置虚拟机,
    在eclipse.ini文件中要写成这样:
    -vm 
    C:/Java/jre1.6.0/bin/javaw.exe 
    -vmargs 
    -Xms128M 
    -Xmx512M 
    -XX:PermSize=64M 
    -XX:MaxPermSize=128M 
    实际运行的结果可以通过Eclipse中“Help”-“About Eclipse SDK”窗口里面的“Configuration Details”按钮进行查看。
    另外需要说明的是,Eclipse压缩包中自带的eclipse.ini文件内容是这样的:
    -showsplash 
    org.eclipse.platform 
    --launcher.XXMaxPermSize 
    256m 
    -vmargs 
    -Xms40m 
    -Xmx256m 
    其中–launcher.XXMaxPermSize(注意最前面是两个连接线)跟-XX:MaxPermSize参数的含义基本是一样的,我觉得唯一的区别就是前者是eclipse.exe启动的时候设置的参数,
    而后者是eclipse所使用的JVM中的参数。其实二者设置一个就可以了,所以这里可以把–launcher.XXMaxPermSize和下一行使用#注释掉。

    4. 其他的启动参数。 如果你有一个双核的CPU,也许可以尝试这个参数:
    -XX:+UseParallelGC
    让GC可以更快的执行。(只是JDK 5里对GC新增加的参数)

    补充:
      如果你的WEB APP下都用了大量的第三方jar,其大小超过了服务器jvm默认的大小,那么就会产生内存益出问题了。
    解决方法: 设置MaxPermSize大小 
    可以在myelipse里选中相应的服务器比如tomcat5,展开里面的JDK子项页面,来增加服务器启动的JVM参数设置:
    -Xms128m 
    -Xmx256m 
    -XX:PermSize=128M 
    -XX:MaxNewSize=256m 
    -XX:MaxPermSize=256m
    或者手动设置MaxPermSize大小,比如tomcat,
    修改TOMCAT_HOME/bin/catalina.bat,在echo "Using CATALINA_BASE: $CATALINA_BASE"上面加入以下行: 
    JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m

    建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以减少jar 文档重复占用内存

    展开全文
  • Java 开发对JVM(Java虚拟机)的了解很有必要,网上看到,收集整理转载一下,方便日后的懒人计划 堆(Heap)和堆(Non-heap)内存  ...”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM
  • -XX:MaxPermSize:最大永久区; JDK1.8使用元数据区替代永久区: 默认情况下,元数据区只受系统可用内存的限制; -XX:MaxMetaspaceSize:用来指定永久区的最大可用值; 栈配置 栈是每个线程私有的内存空间; 在...
  • -server -XX:PermSize=128M -XX:MaxPermSize=256m
  • weblogic加载jsp预编译出现内存溢出,OutOfMemoryError: PermGen space java.lang.OutOfMemoryError: PermGen space 一查是MaxPermSize设置的太小了,想调大一点,但同事说系统参数max locked memory=64设置的不够,...
  • -XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配 我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义。 1)堆(Heap)和堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆...
  • 堆和非堆内存 按照官方的说法:“Java 虚拟机具有一个堆(Heap),堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap ...
  • 虚拟机还有一些内存用于方法区,线程栈和直接内存的使用。方法区配置: 方法区主要存放类的元信息。 在JDK1.6和1.7版本中,可以使用-XX:PermSize和-XX:MaxPermSize配置永久区大小。其中-XX:PermSize表示初始的永久...
  • jvm堆内存的设置

    2020-06-21 21:58:45
    -XX:PermSize=64M JVM初始分配的非堆内存 -XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配 我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义。 1)堆(Heap)和堆(Non-heap)内存 按照...
  • java 非堆 内存

    千次阅读 2016-06-14 22:30:45
    ”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;堆就是JVM留给自己用
  • JVM堆内存详解

    千次阅读 2020-11-01 21:35:28
    JVM内存划分为堆内存非堆内存堆内存分为年轻代(Young Generation)、老年代(Old Generation),非堆内存就一个永久代(Permanent Generation)。 年轻代又分为Eden和Survivor区。Survivor区由FromSpace和To...
  • Java虚拟机(四):堆与堆的内存分配,以及配置更快的Eclipse ... ...一.JVM堆内存分配 ...二.JVM非堆内存分配 三.利用上述所学配置更快的Eclipse 一.JVM堆内存分配 1.1:JVM
  • 4种方式配置不同作用域的jvm的堆栈内存! 1、Eclise 中设置jvm内存: 修改eclipse的配置文件,对所有工程都起作用  修改eclipse根目录下的eclipse.ini文件  -vmargs //虚拟机设置  -Xms40m //初始内存  -Xmx...
  • 来源: ...java内存组成介绍:(Heap)和非堆(Non-heap)内存 java内存组成介绍:(Heap)和非堆(Non-heap)内存  按照官方的说法:“Java 虚拟机具有一个是运行时数据区域,所有类实例和数组的
  • JVM堆内存(heap)详解

    万次阅读 多人点赞 2018-09-10 11:10:11
    JAVA堆内存管理是影响性能主要因素之一。 堆内存溢出是JAVA项目非常常见的故障,在解决该问题之前,必须先了解下JAVA堆内存是怎么工作...JVM内存划分为堆内存非堆内存堆内存分为年轻代(Young Generation)、老...
  • 目录: bea\user_projects\domains\XXX_domain\bin(如:D:\oracle\Middleware\user_projects\...MaxPermSize:PermGen(Class和Meta存放区域)区域内存最大值。   注意: WLS_MEM_ARGS_64BIT 为jdk是64位
  • 永久代” 、“非堆”, 它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为16MB,最大值为64MB(未验证),可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小。 ...
  • “在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和堆。 简单来说堆就是Java代码可及的内存,是留给开发人员使用的; 堆就是JVM留给 自己用的,所有方法区、JVM...
  • XX:PermSize=64M -XX:MaxPermSize=128M-vmargs 说明后面是VM的参数,所以后面的其实都是JVM的参数了-Xms128m JVM初始分配的堆内存-Xmx512m JVM最大允许分配的堆内存,按需分配-XX:PermSize=64M JVM初始分配的非堆...
  • 解决方案 在 catalina.bat 里的 蓝色代码前加入: set JAVA_OPTS=%JAVA_OPTS%-server -Xms800m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m echo Using CATALINA_BASE: "%CATALINA_BASE%" 以下为 区别说明 : ...
  • 需求1:跑大sql内存不够用 虽然知道怎么改,但是对这几个配置一直是模糊不清晰,所以特意在下面写下,我所知道的。 需求2:Eclipse崩溃,错误提示: MyEclipse has detected that less than 5% of the 64MB of...
  • jvm堆内存非堆内存

    千次阅读 2014-03-06 12:50:45
    堆(Heap)和堆(Non-heap)内存...”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;堆就是JVM留给
  • 修改tomcat的初始大小和最大大小 要添加在tomcat 的bin 下catalina.sh 里,位置cygwin=false前 。注意引号要带上,红色的为新添加的. # OS specific support. $var _must_ be set to either true or false.JAVA...
  • Java堆内存初始大小

    千次阅读 2019-06-28 10:08:19
    Java堆内存初始大小 大厂面试题: 1、JVM垃圾回收时候如何确定垃圾?是否知道什么是GC Roots 2、你说你做过JVM参数调优和参数配置,请问如何盘点查看JVM系统默认值 3、你平时工作中用过的JVM常用基本配置参数有...
  • JVM参数设置以及查看堆内存的大小

    千次阅读 2018-12-10 15:40:14
     -XX:MaxPermSize 非堆内存最大值,默认物理内存的1/4, 5. 典型JVM参数设置:  java -Xmx128m -Xms128m -Xmn64m -Xss1m  -Xmx128m:设置JVM最大可用内存为128M。  -Xms128m:设置JVM最小内存为128m...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,502
精华内容 14,200
关键字:

maxpermsize非堆内存