• java垃圾收集器与内存分配策略


      为什么我们还要去了解GC和内存分配呢?当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。
      每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的(尽管在运行期会由JIT编译器进行一些优化,但在基于概念模型的讨论中,大体上可以认为是编译期可知的),因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。而Java堆和方法区则不一样,一个按口中的多个实现类需要的内存可能不一样, 一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间时才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存。

      分析对象是否存活(可达性分析算法):基本思路就是通过-一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(ReferenceChain),当一个对象到GCRoots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

       如图,对象object 5、o5ject 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

      在java中,可作为GC ROots的对象包括:

        ①虚拟机栈(栈帧中的本地变量表).中引用的对象。

        ②方法区中类静态属性引用的对象。

        ③方法区中常量引用的对象。

        ④本地方法栈中JNI(即一-般说的Native方法)引用的对象。 

      即使在可达性分析算法中不可达的对象,也不是非被回收的,这时候它们暂时处于“缓刑” 阶段。

        要真正回收一个对象,至少要经历两次标记过程。如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是:此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行。

        如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Qucue的队列之中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样做的原因是,如果一个对象在finalize()方法中执行缓慢,或者发生了死循环(更极端的情况),将很可能会导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃。finalize()方法是对象逃脱被回收命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()中成功拯救自己,只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的被回收了。  

      永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类

        回收废弃常量与回收Java堆中的对象非常类似。以常量池中字面量的回收为例,假如一个字符串“abc”已经进入了常量池中,但是当前系统没有任何一个String 对象是叫做“abc” 的,换句话说,就是没有任何String对象引用常量池中的“abc”常量,也没有其他地方引用了这个字面量,如果这时发生内存回收,而且必要的话,这个“abc”常量就会被系统清理出常量池。常量池中的其他类(接口)、方法、字段的符号引用也与此类似。                       

        判定一个常量是否是“废弃常量”比较简单,而要判定一个类是否是“无用的类”的条件则相对苛刻许多。类需要同时满足下面3个条件才能算是“无用的类”

          1.该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。

          2.加载该类的ClassEoader已经被回收。

          3.该类对应的 java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

    虚拟机可以对满足上述3个条件的无用类进行回收,仅仅是“可以”,而并不是和对象一样, 不使用了就必然会回收。

      

  • 相关阅读:
    use tomcat to access the file cross the environment
    data audit on hadoop fs
    Good practice release jar to Nexus
    套路!从Ruby 到 Cocoapods的发布
    单元测试之NSNull 检测
    UIwebView 和 H5交互详情
    IT 需要知道的一些专业名词和解释 (长期更新)
    Git 操作 学习资源 网址
    GCD
    软件工程——个人总结
  • 原文地址:https://www.cnblogs.com/hoooo/p/12492087.html
Copyright © 2020-2023  润新知