Jvm内存区以及垃圾回收算法

Java虚拟机运行时数据区域被分为五个区域:堆(Heap)、栈(Stack)、本地方法栈(Native Stack)、方法区(Method Area)、程序计数器(Program Count Register)

堆
    Java Heap是Java虚拟机管理的内存的最大一块,这块区域随着虚拟机的启动而创建。在实际的运用中,我们创建的对象和数组就是存放在堆里面。
    如果你听说线程安全的问题,就会很明确的知道Java Heap是一块共享的区域,操作共享区域的成员就有了锁和同步。
    与Java Heap相关的还有Java的垃圾回收机制(GC),Java Heap是垃圾回收器管理的主要区域。程序猿所熟悉的新生代、老生代、永久代的概念就
    是在堆里面,现在大多数的GC基本都采用了分代收集算法。如果再细致一点,Java Heap还有Eden空间,From Survivor空间,To Survivor空间等。

栈(Stack)
 Java Stack是线程私有的,她的生命周期与线程相同。Java Stack描述的是Java方法执行时的内存模型,每个方法执行时都会创建一个栈帧(Stack Frame)
 用语存储局部变量表、操作数栈、动态链接、方法出口

本地方法栈
  本地方法栈(Native Stack)与Java虚拟机站(Java Stack)所发挥的作用非常相似,他们之间的区别在于虚拟机栈为虚拟机栈执行java方法(也就是字节码)
  服务,而本地方法栈则为使用到Native方法服务

方法区:很多人都更愿意把方法区称为“永久
   方法区(Method Area)与堆(Java Heap)一样,是各个线程共享的内存区域,它用于存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据

线程私有的数据区域有:
    Java虚拟机栈(Java Stack)
    本地方法栈(Native Stack)

线程共有的数据区域有:
    堆(Java Heap)
    方法区

堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
堆的大小可以通过参数 –Xms、-Xmx 来指定。

新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2( 该值可以通过参数 –XX:NewRatio 来指定 ) 新生代 ( Young ) = 1/3 的堆空间大小。
老年代 ( Old ) = 2/3 的堆空间大小。
新生代 ( Young ) 被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,默认的Edem : from : to = 8 : 1 : 1 

JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。

GC 分为两种:Minor GC、Full GC ( 或称为 Major GC )。
        1.Minor GC 是发生在新生代中的垃圾收集动作,所采用的是复制算法。
    a、新生代几乎是所有 Java 对象出生的地方,即 Java 对象申请的内存以及存放都是在这个地方。
    b、Java 中的大部分对象通常不需长久存活,具有朝生夕灭的性质。
    c、当一个对象被判定为 “死亡” 的时候,GC 就有责任来回收掉这部分对象的内存空间。
    d、新生代是 GC 收集垃圾的频繁区域。
    e、当对象在 Eden(+from) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域        
        所容纳( 这里应为 to 区域 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,
    f、 然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,
    g、以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,
    h、当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 ),这些对象就会成为    
            老年代。
    j、但这也不是一定的,对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。

    复制算法
    1、将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
    2、当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。


    2.Full GC 是发生在老年代的垃圾收集动作,所采用的是标记-清除算法。
    a、老年代里面的对象几乎个个都是在 Survivor 区域中熬过来的,它们是不会那么容易就 “死掉” 了的。
    b、Full GC 发生的次数不会有 Minor GC 那么频繁,并且做一次 Full GC 要比进行一次 Minor GC 的时间更长。
    c、标记-清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ),
    d、此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次 GC 的收集动作。

1、标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象
2、在标记完成后统一回收所有被标记的对象  
内存分配与回收策略
    下面是使用Serial/Serial Old收集器下(ParNew/Serial Old收集器组合的规则也基本一致)的内存分配和回收的策略

    对象优先在Eden分配
    1、大多数情况下,对象在新生代Eden区中分配。当Eden区没有足够空间进行分配时,虚拟机将发起一次MinorGC。
    2、执行GC后,将存活的对象分配到Survivor空间
    3、无法放到Survivor空间的对象,分配到老年代
    4、分配到Survivor的对象,经过15次Minor GC后,进入老年代

            新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。
            老年代GC(Major GC/Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的MinorGC(但非绝对的,在Parallel Scavenge收集器的
            收集策略里就有直接进行Major GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上

            大对象直接进入老年代
            1、大对象:需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组
            2、虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配

            长期存活的对象将进入老年代
            1、虚拟机给每个对象定义了一个对象年龄(Age)计数器
            2、如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1。
            3、对象在Survivor区中每“熬过”一次Minor GC,年龄就增加1岁
            4、当它的年龄增加到一定程度(默认为15岁),就将会被晋升到老年代中
            5、对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置

            动态对象年龄判定
            1、为了能更好地适应不同程序的内存状况,虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代
            2、如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄
4. 并行垃圾回收收集器和CMS收集器区别

CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器,如果你的应用程序对停顿比较敏感,并且在应用程序运行的时候可以提供更大的内存和更多的CPU(也就是硬件牛逼),那么使用CMS来收集会给你带来好处。还有,如果在JVM中,有相对较多存活时间较长的对象(老年代比较大)会更适合使用CMS。
G1为了能够尽量的做到准实时的响应,例如估算暂停时间的算法、对于经常被引用的对象的特殊处理等,G1为了能够让GC既能够充分的回收内存,又能够尽量少的导致应用的暂停,可谓费尽心思,从G1的论文中的性能评测来看效果也是不错的,不过如果G1能允许开发人员在编写代码时指定哪些对象是不用mark的就更完美了,这对于有巨大缓存的应用而言,会有很大的帮助,G1将随JDK 6 Update 14 beta发布。
并行收集:并行收集使用多线程处理垃圾回收工作,因而速度快,效率高。而且理论上CPU数目越多,越能体现出并行收集器的优势。(串型收集的并发版本,需要暂停jvm) 并行paralise指的是多个任务在多个cpu中一起并行执行,最后将结果合并。效率是N倍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值