美文网首页
JAVA过关题-JVM内存结构,为什么需要GC

JAVA过关题-JVM内存结构,为什么需要GC

作者: shu2man | 来源:发表于2018-03-11 10:43 被阅读0次

    转自(侵删):http://blog.csdn.net/wangyang665/article/details/38459271

    1. Jvm的内存可以分为堆内存和非堆内存

    1) 堆内存

    Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。

    Java所有实例和数组的内存均在此处分配。对象的对内存

    java垃圾回收器回收。

    堆内存由两部分组成:Eden+Survivor(Fromspace+Tospace)叫做Young Generation(年轻代)和Old Generation(年老代)

    它们分别存放的内容如下:

    Eden----所有新创建的对象

    Survoivor(Fromspace+Tospace)---当Eden的内存空间不足时,会将Eden中依然存活的对象拷贝到Survoivor中的Fromspace或者Tospace中

    Old Generation ---当一个Survivor区域满了的时候,会将该区域中的已历经过多次的依旧存活的对象放到Old Generation中

    2) 非堆内存

    主要包括PermanentGeneration , Jvm Stack(java虚拟机栈), Local Method Statck(本地方法栈)。

    它们分别存放的内容如下:

    PermanentGeneration ---存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,

    Jvm Stack(虚拟机栈)---虚拟机栈是线程私有的,每个线程的创建都会创建虚拟机栈,Jvm Stack中存放当前线程中的局部基本类型变量,部分的返回结果,StackFrame及非基本类型的对象指向堆上的地址。

    Local MethodStatck(本地方法栈)---- JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态。

    1. Jvm的回收机制

    Jvm采用分代回收(Generationcollection)的策略,用较高频率对年轻的对象(Young Generation)进行扫描和回收,这种叫做minor collection,而对老对象(Old Generation)的回收频率要低的多,称为major collection这样就不需要每次GC都将内存中所以的对象都检查一遍。

    当创建一个java对象时,内存申请过程如下:

    1) Jvm会试图为java对象在Eden中初始化一块内存区域

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

    3) Jvm GC机制试图释放在Eden中所有不活跃的对象(这个回收比较频繁)如果释放后Eden空间仍然不足放入新对象,则试图将部分Eden中的存活的对象放入Survivor区中

    4) Survivor区被用来作为Eden及Old Generation中间的交换区域,当Old Generation空间足够时,Survivor区的空间满时候,对象会被移动到Old Generation。

    5) 当Old Generation区空间不够时,Jvm GC回收机制会在Old Generation进行完全的垃圾收集机制。

    6) 完全垃圾收集后,若Survivor及Old Generation仍然无法存放从Eden复制过来的部分对象,导致Jvm无法在Eden为新对象创建内存区域,则出现“out of memory”错误。

    3 Jvm GC回收算法

    1)引用计数算法

    为每一个对象添加一个计数器,计数器记录了对该对象的活跃引用的数量。如果计数器为0,则说明这个对象没有被任何变量所引用,即应该进行垃圾收集。
    收集过程如下:
    A减少被收集对象所引用的对象的计数器的值
    B将其放入延时收集队列之中

    2) 标记-清除收集器算法

    收集过程分为2个阶段
    A.首先停止所有工作,从根集遍历所有被引用的节点,然后进行标记,最后恢复所有工作
    B.收集阶段会收集那些没有被标记的节点,然后返回空闲链表

    标记-清除法的缺点在于
    A.标记阶段暂停的时间可能很长,而整个堆在交换阶段又是可访问的,可能会导致被换页换出内存。
    B.另外一个问题在于,不管你这个对象是不是可达的,即是不是垃圾,都要在清除阶段被检查一遍,非常耗时.
    C.标记清楚这两个动作会产生大量的内存碎片,于是当有大对象进行分配时,不需要触发一次垃圾回收动作

    3) 拷贝收集器算法

    该算法的提出是为了克服句柄的开销和解决堆碎片的垃回收。将内存分为两个区域(fromspace和tospace)。所有的对象分配内存都分配到fromspace。在清理非活动对象阶段,把所有标志为活动的对象,copy到tospace,之后清楚fromspace空间。然后互换fromsapce和tospace的身份。既原先的fromspace变成tosapce,原先的tospace变成fromspace。每次清理,重复上述过程。

    4) 标记-整理收集器算法

    标记整理收集器,通过融合了标记-清除收集器和拷贝收集器的优点,很好的解决了拷贝收集策略中,堆内存浪费严重的问题。
    标记整理收集器分为2个阶段
    1)标记阶段,这个阶段和标记-清除收集器的标记阶段相同
    2)整理阶段,这个阶段将所有做了标记的活动对象整理到堆的底部

    相关文章

      网友评论

          本文标题:JAVA过关题-JVM内存结构,为什么需要GC

          本文链接:https://www.haomeiwen.com/subject/rlvvfftx.html