zoukankan      html  css  js  c++  java
  • Java之GC 如何工作

    一、什么是GC?

    • GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。

    二、GC如何工作?

    引用计数
    • 每个对象都含有一个计数器,当引用连接至对象时+1,引用离开作用域或被置为null时-1。GC遍历全部对象,发现计数器为0的时候就会释放其内存。
    • 优点:简单
    • 缺点:慢、循环引用问题、对象应该被回收但引用计数不为零
    • 引用计数只是为了说明GC的工作方式,但实际上似乎没有任何Java虚拟机实现过。
    根搜索算法
    • 原理:每个“活”的对象,一定能追溯到其存活在堆栈或静态存储区之中的引用。
    • 方法:从堆栈和静态存储区开始,遍历所有引用;然后追踪它所引用的对象,然后是这些对象包含的所有对象,反复进行直至“根源于堆栈和静态存储区的引用”所形成的网络被全部访问完为止
    停止-复制算法
    • 先暂停程序的运行,然后将全部活的对象从当前堆复制到另一个堆,没有复制的都是垃圾;新堆里的对象在内存中时连续的
    • 不属于后台回收模式,因为要暂停程序的运行
    • 把对象从一个堆复制到另一个堆时,所有指向它们的引用都必须要修正。
    • 效率低的原因(1):需要两个分离的堆,因此需要两倍的内存空间
    • 效率低的原因(2):程序稳定后垃圾很少,即需要存活的对象远大于垃圾数量,此时复制到另一个堆非常浪费。
    标记-清扫算法
    • 用根搜索算法找到所有存活的对象并标记(此过程不回收),当全部标记工作完成的时候,清理所有没有标记的对象
    • 缺点(1):导致内存空间不连续
    • 缺点(2):也会暂停程序
    分代算法
    • JVM中,内存以较大的“块”为单位;如果对象比较大,它会占据单独的块;有了块之后,GC就可以在回收的时候往废弃的块中拷贝对象了
    • 每个块用相应的代数(generation count)来记录是否存活;如果块在某处被引用,其代数会增加;GC会对上次回收动作之后新分配的块进行整理
    • GC会定期进行完整的清理动作,大型对象不会被复制但是其代数会增加;小型对象的那些块则被复制并整理
    自适应、分代的、停止复制、标记清扫方式
    • JVM会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到标记-清扫模式;同样,JVM会跟踪标记-清扫的效果,要是堆空间出现很多碎片,就会切换回停止-复制模式。
    其他附加技术

    即时编译器(Just-In-Time JIT):可以把程序全部或部分翻译成机器码来提高运行速度。当需要装载某个类时,编译器会先找到其.class文件,然后将该类的字节码装入内存。此时,有两种方案可供选择:

    • 让即时编译器编译所有代码:这种操作散落在整个程序的声明周期内,累加起来耗时更长;会增加可执行代码的长度,造成页面调度
    • 惰性评估:意思是即时编译器只在必要的时候才编译代码,这样,从不会被执行的代码也许就压根不会被JIT所编译。
  • 相关阅读:
    Vue总结
    Android适配总结
    Java为什么需要四种引用?
    回溯递归:八皇后
    eclipse中的maven build 、maven clean 、 maven install作用
    JS时间格式CST转GMT
    什么是ECMAScript、什么又是ECMA?
    maven打包工程出现错误 Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test
    Vue三步完成跨域请求
    Eclipse导入别人项目爆红叉
  • 原文地址:https://www.cnblogs.com/lanqingyu/p/12356706.html
Copyright © 2011-2022 走看看