`
zhaohaolin
  • 浏览: 991830 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JVM & Memory (4) gc

    博客分类:
  • JVM
阅读更多

不同的JVM实现对堆结构的设计有所不同,这里先说说共性的,然后再比较classic vm和hotspot vm在gc方面的差异。

先 大致说说gc的过程,通常有两种情形会导致gc发生,一种是显式的System.gc()调用而java进程未禁止显示gc,第二种是隐式的,即内存管理 器(MM)在alloc内存时发生failure,MM进而作gc以便释放出空间用于分配(当然,假如gc后还是没有空间可满足分配数 值,OutOfMemory就发生了)。gc过程分3步走,第1步,mark阶段,标示出allocbits和markbits,allocbits 代表当前java heap中存在的对象所占内存的bit映射,markbits代表所有reachable对象所占内存的bit映射,是allocbits的子集。这一 步,一般是要锁定java heap的,但有些gc器能做到并发/并行mark(后面有解释)。第2步,sweep阶段,即将markbits和allocbits的补集所代表的内 存区域作回收,这也包括对class的回收,假如classgc未被禁用,而jvm确实找到了未被使用的class,那么除了java heap中的Class对象被回收,method area里该class的method data也被释放。第3步,compact阶段(可选的,jvm会自行判断是否进行该步),整理碎片,两种技巧,一种是移动琐碎的对象区域,使之连续,一种是移动琐碎的free区域,也使之连续。
这步也必须要锁定java heap。compact时还要做一个工作,即将所移动的对象的原始引用值作同步更新。这时存在一个问题,假如某thread stack里的一个浮点数碰巧看起来像是一个对象引用值 (内存泄露也会因此情形而发生) ,那么jvm因为无法断定而放弃移动该对象,等待以后再移动(据称,hotspot vm对精确判定引用值的问题解决的较好)。

再 解释一下mark阶段,为了得到markbits,首先要收集root references,也就是java thread stacks refs, jni global refs,thread moniters,interned strings,and soft/weak refs等,它们是对象引用的源头,从root referent object顺藤摸瓜,即可把所有reachable object标示出来。再解释一下bits映射,每一个bit代表每一个内存GRAIN(是分配的最小粒度),假设GRAIN是8 byte,那么对于64M的堆,需要额外的1M的bits来映射,这部分额外开支需要gc器向c heap申请,当堆扩展和收缩时,markbits也要随之变动。mark阶段工作量比较大,因为要扫描和遍历,所以后期的jvm都采用多种新的方式如 concurrent(普通线程也参与mark)或parallel(多cpu有效)进行mark。

再说堆的扩张(Expansion) 和收缩(Shrinkage)。当内存不足时,gc清理一遍后还发现free空间不能满足分配的尺寸要求,那么它有两种手段继续推进,如果最大堆 (-Xmx)未达到,那么扩展堆,如果已达到,那么强制回收soft/weak referents,如果此时还不能满足,那么OutOfMemory就发生了。而当经过一段运行时间后,jvm判断free区域较多(不同的jvm判定 依据有所不同),那么就会收缩java heap。收缩的好处有两个,1是减轻OS的负担,2又减少了jvm内存管理器的维护成本。注意,不论再怎么收缩,也不可能小于最小堆(-Xms)。默认 的ms值和mx值各vm提供商有所不同,请参阅其文档。

个人认为主流的jvm主要有3种,sun classic, ibm classsic,sun hotspot。sun classsic用于1.3.0以前,之后sun的jvm都是hotspot。而ibm的jdk一直是classsic,不知其5.0的vm是否会采用 hotspot。sun的是主流无可置疑啦,为什么扯上ibm的呢,因为看过一个民间的性能评测结果,ibm 1.42vm比sun的1.42vm甚至略好。sun classic使用间接句柄分配对象,所以堆分为两部分,一块放object,一块放handle。这个好处是compact方便得很,缺点也是很严重的 缺点,是对象访问不直接,要多一层指针转换,对性能大有影响。ibm classic的具体细节的资料比较缺乏,但根据其white paper,似乎使用的是直接句柄(否则性能无法比sun的好),另外它将java heap划分成system heap和一般heap,仅将jvm的系统class和对象分配到system heap里,它还支持并行和并发的gc。sun hotspot使用直接句柄,似乎又采用了一些高级手段,做到了精确辨别,因此快而且回收准确,另外提供了多种的gc器,适用于不同场合。值得一提的是它 的代生gc器(Generational Copying Collection),根据对象生命周期模型(小对象居多,生命周期短),使用类似stack的方式,将同一时期产生的对象放在同一容器 (nursery)中,这批对象基本上会同时消亡,这样,回收时可直接将
容器 释放,避免了繁琐的逐个对象释放的过程,因此可以减少gc的花费时间(duration)和频度(frequency),并且 容器 是现成的,所以分配时,寻找free空间很方便,所以提高了分配的效率。

本篇再加上前面的几篇,已经把JVM和Memory相关的主要机理和过程都已经覆盖了,下一篇主要是关于tuning和trouble shooting,请关注。

补: 再说一下内存泄露(memory leak),与c/c++的内存泄露的概念不同,java的memory leak是指无用(unused)的对象因为仍然是reachable的,所以不能被gc,因而造成内存的被白白占用。造成memory leak的原因是多样的,比如程序未及时给变量赋null,再比如上文提到的浮点数被碰巧当成对象引用,或者jni程序里声明的global ref忘了做撤销。对于服务器程序来说,memory leak的逐渐积累,只要运行时间足够,必然造成OutOfMemory。如何确定jvm是否有内存泄露呢,假使你没有监测工具也不要紧,打开- verbose:gc开关,运行系统足够长的时间(约收集20到50次gc的数据),然后将verbosegc的信息作收集,察看java heap的谷值(gc后java heap的大小,峰值则表示gc前java heap的大小)是否有递增的倾向,如果倾向明显,那么很有可能是memory leak问题。

分享到:
评论

相关推荐

    JVM Memory Model and GC.pdf

    JVM Memory Model and GC.pdf

    MemoryAnalyzer-JVM

    MemoryAnalyzer-jvm内存分析工具,可以将转储的dump文件解析成图形化,能够清晰的看到项目的内存占用情况以及gc回收详情

    MemoryAnalyzer(JDK11)-1.12.0.20210602-win32.win32.x86_64_.zip

    Memory Analyzer Tool(MAT)工具是 eclipse 的一个插件(MAT 也可以单独使用),它分析大内存的 dump 文件时,可以非常直观的看到各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系、利用 OQL 对象查询,...

    JVM的基础和调优【JMM 内存结构 GC OOM 性能调优 ThreadLocal】

    JVM的基础和调优【JMM 内存结构 GC OOM 性能调优 ThreadLocal】 内存泄露:是指程序在申请内存后,无法释放已申请的内存空间就造成了内存泄露, 一次的内存泄露似乎不会有大的影响,但是内存泄露堆积的后果就是内存...

    resin-jvm 调优

    1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。 ...

    无私奉献-jvm面试备战

    OutOfMemoryError 异常有多种场景,包括 java.lang.OutOfMemoryError: Java heap space、java.lang.OutOfMemoryError: GC overhead limit exceeded 和 java.lang.OutOfMemoryError: Direct buffer memory 等。

    JVM参数设置详细说明

    在使用concurrent gc的情况下,防止memory fragmention,对live object进行整理,使memory 碎片减少 h: -XX:CMSInitiatingOccupancyFraction= 指示在old generation 在使用了n%的比例后,启动concurrent collector,...

    Elasticsearch集群中JVM问题的应对之策

    Elasticsearch集群中JVM问题的应对之策 Elasticsearch集群中JVM问题的应对之策

    JVM内存调优深入文章共享

    最近总结JVM内存调优的一些东西,基本上是网上一些资料的汇总。 文章从算法,垃圾回收机制等多个方面对JVM的工作机制进行描述,使读者对JVM 有个全面的了解。

    【Spark调优篇04】Spark之JVM调优1

    在 Spark 中,JVM 调优是非常重要的,因为 full GC/minor GC 都会导致 JVM 的工作线程停止工作,即 stop the world。这样会影响 Spark 的性能,并且可能导致 Spark 的频繁停止工作。 降低 cache 操作的内存占比 ...

    JVM内存分析工具HeapAudit.zip

    你是否看见过java.lang.OutOfMemory这些类似的错误信息?判断一个系统好坏,高性能非常重要。而阻碍系统性能提高的第一大元凶就是内存问题,更糟糕的是如果GC不能完全释放无用的内存,这会导致内存溢出,从而产生更...

    java8源码-jvm-study:jvm-study

    jvm-study 方法执行过程 jvm申请内存 初始化运行时数据区 方法区:存放 class;静态变量:常量 堆:实例对象 栈:栈帧(对象的引用,方法) 类加载 执行方法 创建对象 堆空间分代划分 outOfMemory异常 ...

    jvm调优的一些相关参数

    应用出现OutOfMemory等内存异常,应用中有使用本地缓存且占用大量内存空间,系统吞吐量与响应性能不高或不降,Heap内存(老年代)持续上涨达到设置的最大内存值,Full GC 次数频繁。等有解决方法 JVM调优主要是针对...

    内存管理白皮书(英文))

    2.take a deep look inside the JVM memory management model 3.introduce how to choose a suitable GC strategy and how to configure your JVM for your application 4.introduce the key options for JVM ...

    JVM面试专题

    4、Perm Space中保存什么数据?会引起OutOfMemory吗? 5、什么是类的加载 6、如何⾃定义⼀个类加载器?你使⽤过哪些或者你在什么场景下需要⼀个⾃ 定义的类加载器吗? 7、描述一下JVM加载class文件的原理机制? 8、...

    内存泄露分析工具Memory_Analyzer_Tool(MAT)介绍.docx

    例如,可以设置JVM启动参数,增加set JAVA_OPTS= -verbose:gc -Xloggc:../logs/gclog.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError %JAVA_OPTS%,其中红色...

    超硬核!!!一篇文章搞定整个JVM运行时数据区

    JVM运行时数据区1 JVM运行时数据区2 解析JVM运行时数据区2.1 方法区(Method Area)2.2 Java堆(Java Heap)2.3 程序计数器(Program Counter ...3.1 JVM字节码执行引擎3.2 垃圾收集系统3.3 直接内存(Direct Memory)...

    JAVA内存优化-毕玄[归纳].pdf

    JVM 提供了多种监控方法来查看内存区域的变化和 GC 的工作状态,包括: * `jstat –gcutil`:查看堆中各个内存区域的变化和 GC 的工作状态。 * `-XX:+PrintGCDetails –Xloggc:<file>`:输出 GC 的状况到日志文件。...

Global site tag (gtag.js) - Google Analytics