JVM内存分析

JVM内存组成结构

JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)

JVM内存分析_第1张图片

1)堆

所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由From Space和To Space组成,结构图如下所示:

JVM内存分析_第2张图片

  • 新生代。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例
  • 旧生代。用于存放新生代中经过多次垃圾回收仍然存活的对象

2)栈
  每个线程执行每个方法的时候都会在栈中申请一个栈帧,每个栈帧包括局部变量区和操作数栈,用于存放此次方法调用过程中的临时变量、参数和中间结果
3)本地方法栈
  用于支持native方法的执行,存储了每个native方法调用的状态

4)方法区
       存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用持久代(Permanet Generation)来存放方法区,可通过-XX:PermSize和-XX:MaxPermSize        来指定最小值和最大值


垃圾回收机制

JVM分别对新生代和旧生代采用不同的垃圾回收机制

新生代的GC: 新生代通常存活时间较短,因此基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中,对应于新生代,就是在Eden和From Space或To Space之间copy。新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从eden到survivor,最后到旧生代, 用java visualVM来查看,能明显观察到新生代满了后,会把对象转移到旧生代,然后清空继续装载,当旧生代也满了后,就会报outofmemory的异常,如下图所示:

JVM内存分析_第3张图片

旧生代的GC: 旧生代与新生代不同,对象存活的时间比较长,比较稳定,因此采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,总之就是要减少内存碎片带来的效率损耗。


在java的垃圾回收中,jvm是如何判断堆中的对象是否可以被回收?主流的判断方法有两种:

1.引用计数算法:  概  述:给对象添加一个引用计数器,每有一个地方引用这个对象,计数器值加1,每有一个引用失效则减1,当进行垃圾回收时如何判断该引用的数量为0,此时就代表没有      进行任何对象对其进行引用应用实例:微软的COM,AS3的FlashPlayer,Python 优   点:实现简单、判定效率高 缺   点:无法解决循环引用的问题。两个对象objA和objB相互引用,如果用计算器算法的话会导致无法进行回收
2.根搜索算法:  如下图对象object5,object6,object7虽然互相有关系,但是没有GC roots可以达到他们。所以他们时可以被回收的对象。
概述:从GC Root作为起点,向下搜索它们引用的对象,可以生成一颗引用树,该引用树之外的对象都将被回收,树的节点视为可达对象,反之视为不可达。

JVM内存分析_第4张图片

问:不可达对象一定会被回收吗 答:不是。执行垃圾回收前JVM会执行不可达对象的finalize方法,如果在此方法中对象将自己与GC Root链关联,该对象变为可达,则不会回收它。   但一个对象的finalize方法只会被执行一次。

应用实例:Java,C#,Lisp都使用这种算法

java中只有一下的对象才可以被作为GC Root:          1>虚拟机栈(栈帧中的本地方法表)中引用的对象。 
2>方法区中类静态属性引用的对象。 
3>方法区中常量引用的对象。 
4>本地方法栈JNI(即一般说的Native方法)的引用对象。 
 

3.关于引用:    分为:强引用(Strong Reference),软引用(Soft Reference),弱引用(Weak Reference),虚引用(Phantom Reference)四种。    3.1 强引用。      该引用是代码中普通存在的,例如Object objA = new Object(),只要强引用存在,垃圾收集器永远不会回收掉被引用的对象。    3.2 软引用。     该引用用来描述一些还有用,但是并非必须得对象,在系统将要爆发内存溢出之前,将会把这些对象列在进行回收的范围之内,进行二次回收后如果还是内存不足,这时候才跑出内存溢出的错误。      该引用也是用来描述非必须对象的,强度比软引用更弱被若引用引用的对象只能存活到下一次垃圾回收之前。    3.4 虚引用也称为幻影引用。      是最弱的一种的引用,一个对象是否存活与其生存周期没有什么影响,设置该引用的目的仅仅 是希望这个对象被释放的时候能够收到一个系统通知。    3.3 弱引用。 


你可能感兴趣的:(java,jvm,算法,内存)