jvm-GC篇

一、何为gc?为何要了解gc以及怎样去合理运用gc机制?

    gc (gabage collection) 意思就是垃圾回收,java的gc功能可以在某种情况下自动回收无用的对象以达到释放内存空间的好处,否则可能会随着系统的运行导致系统崩溃等一系列的问题。

     让我们接下来轻松愉快的去了解gc吧^_^

    了解gc之前首先让我们了解一下几个基本的定义:

1.:函数本身,函数中的变量本身----(线程私有,函数为单位,直接弹“栈帧”)

2.:new出的对象(1.7以前方法区也在堆上,1.8以后,单独有个元数据区,线程共享)

3.方法区:类相关,静态变量就在类上,运行时常量(string).静态数据区什么的都指方法区,叫法不同。(线程共享)

        方法区:是根据所存内容的划分--与之对应的分类是堆,栈....。例如称为如持久带,永久代,permgen都行,这是针对"gc分代"的划分的。自1.8以后也更名“元数据”当然也有具体实现的不同。

(上面几点涉及到知识点很多,这里不再赘述,如果上面不太理解对下面的gc无影响)

    可参考下图:

        gc主要是针对的是“堆”和“方法区”,其实主要针对的是堆。

二、何为垃圾?

        既然gc是针对“堆”即对象存储的区域,因此就存在对象越来越多,还好java的可达性分析可以判断出哪些是有用的对象哪些是无用对象。

        可达性分析:

                起点:所有线程的栈、方法区(常量,静态变量)

                把起点的所有变量遍历一遍,看有没有谁没被起点的变量所引用,如果有存在对象不被起点的变量所引用,即使在堆中该对象和另外一个类似的对象相互引用,则都判断这个对象就是垃圾。

                安全点(扩充即安全区域):Ooopmap,无论如何必须stop the holeworld 

                即在做垃圾分析的时候必须所有线程停下来(各自跑到离自己最近的安全点(区域))等待gc的分析,因为你不能它在一边收集的时候一边分配对象,否则就会认为你这对象是垃圾。

           对于对象的引用还有几种区分(平时的“强引用(new)”、“软引用(SoftReference)”、“弱引用(WeakReference)”、“虚引用(PhantomReference)”),当然这一般用不到。

三、垃圾回收策略(怎么回收垃圾)

        3.1 标记清除(Mark-Sweep)快

            此方法简单,快,但是有很大的缺点。此方法就是在可达性分析过后把垃圾对象标记出来,然后把对象清除。能不能发现到此方法的缺点?

    缺点:相当于造成内存碎片化,空余区域不连续,如果想再存储一个连续内存超过多个块的区域就分配不下了!从而造成内存浪费,相当于用同一个桶来装石头不如装的水体积多。

    3.2 标记整理(Mark-Sweep)慢

    此方法和3.1的类似,也是标记处垃圾然后清除,但是这做了一步整理内存操作,把有用的内存整理得整整齐齐。所以去整理有用对象的时候就会花费大量时间。

        好处:稳定

        缺点:慢

     3.3 复制(Coping)折中(空间换时间)

在before gc的时候把内存区域分成两半,当分析完垃圾过后,直接把左边的有用对象复制到右边去按着放在一起,复制完过后把整个左半边又标记为不可用。这样就只用了一次复制消耗的时间。

        慢在要整理,快在不用再挨个去清除。

上图只是一个这种“复制”方法的一个模型,具体的实现细节再看下面一一道来:

分析:

        如上图所示

        1、最开始产生对象的时候首先放在 Eden里面,当Eden放满过后再往S1里面放。一旦开始垃圾回收的时候,将Eden和S1里面的所有非垃圾对象复制到S2里面。然后直接把Eden和S1标记为可用空间(相当于清空)。

        2、再次产生对象的时候往Eden和S2里面放,一旦开始gc的时候,将Eden和S2里面的非垃圾对象复制到S1里面。然后直接把Eden和S2标记为可用空间。

      复制算法的深度分析:
          每次回收很比例:空间代价
          每次回收很比例:空间代价

    于是有了分代

    分代:
         
按稳定程度(gc轮数)分为年轻,老年代
          新对象一开始进入年轻代,空间不足,年轻代Minor  GC(默认15轮,一般还有比例限制),还没被回收则进入老年代.老年代空间不足Major GC/FullGC.
         
新生代young:每次回收很大比例
          老年代old:每次回收很小比例,大部分情况下是标记整理。
PS:15这个次数动态变化,不足是有比例,类似hashmap装载因子(动态扩容,不一定满了再扩)

注:在JDK1.8已经没有永久代,详细信息请参考文章https://blog.csdn.net/cwchenwan/article/details/81145898

猜你喜欢

转载自blog.csdn.net/cwchenwan/article/details/79874158