疯狂java笔记:java的内存回收

对象状态

  1. jvm垃圾回收机制是否回收一个对象,取决于是否还有引用变量指向该对象。
  2. 对象引用可以理解成有向图,引用变量指向对象,构成从一点可以到达另一点的可到达状态。
  3. 根据有向图的状态,可以将堆内存中的java对象分为三种状态:
    1).可到达状态,即在有向图中可以导航到该对象。
    2).可恢复状态,指没任何引用变量指向该对象,处于等待jvm调用其finalize方法清理资源。如果在finalize方法调用期间出现了指向该对象的引用变量,则该对象恢复成可到达状态,否则变成不可恢复状态。
    3).不可恢复状态,系统会真正开始回收该对象所占用的资源。

引用类型

  1. 强引用:创建一个对象并把这个对象赋值到一个引用变量,这个引用变量就是强引用。
  2. 软引用:通过java.lang.ref包中的SoftReference类实现,该类引用变量只有在系统内存不足时才回收这些引用类型对象变量的内存空间。
  3. 弱引用:通过WeakReference类实现,其引用级别比弱引用低,启动垃圾回收机制后该类引用的对象所占内存一定被回收。与其功能类似的还有WeakHashMap,在gc启动后回收没有强引用到的键值对,即清空该类型的Map。
  4. 虚引用:通过PhantomReference类实现,完全类似没有引用,需要配合ReferenceQueue使用。使用虚引用的对象只有在垃圾回收机制运行后,才会被加入到与该虚引用关联的引用队列中去。

关于java的内存泄露

  1. java的内存泄露产生根本原因是:程序中有一些java对象,它们处于可到达状态,但程序以后都不会使用到它们,而且它们的所占内存也不会被回收,那么它们所占用的空间就可以算是内存泄露了。
  2. 对应程序中不会在使用的对象,要在程序中赋值成null。
  3. 可用内存检测工具来监控内存的使用,这些工具包括Optimizeit Profiler,JProbe Profiler,JinSight , Rational 公司的Purify等。
  4. IBM上说了:Java也存在内存泄露问题,其原因主要是一些对象虽然不再被使用,但它们仍然被引用。
  5. 产生原因有:静态集合类,物理连接,监听器。

垃圾回收机制

  • 垃圾回收基本算法
    1.串行回收:一个CPU执行垃圾回收;
    2.并行回收:多个CPU执行垃圾回收,缺点是易产生内存碎片。
    3.并发执行:需要解决与应用程序在回收过程中修改对象的冲突问题,系统开销比较高,需要更多堆内存。
    4.应用程序停止:回收过程中会导致应用程序停止执行。Stop-the-world
    5.压缩:把活动的对象迁移到所在内存区域一段连续的范围中去,把剩余的内存区域释放。
    6.不压缩:仅仅把垃圾内存清空,最后导致内存碎片增多。
  • 具体实现方法:
    1.复制:把堆内存分为两个区域,把从跟可到达的对象全部复制到新的内存区域,然后把原先的内存区域回收。
    2.标记清除:把从根可到达的对象全部标记为可到达状态,然后遍历整块内存,把没有标记的内存回收掉。
    3.标记压缩:把从根可到达的对象全部标记为可到达状态,然后把已标记的对象迁移到所在内存区域一段连续的范围中去,再清除原先内存块中不可到达的对象所占用的空间,可避免内存碎片的产生。
  • 堆内存分代回收
    1.分代依据:对象生成时间长短
    2.分为以下三代:
    1).Yong代:由一个Eden,两个Survivor构成。新生对象存在于Eden代内存区域中,Survivor代中保持至少经历一次垃圾回收的对象。由于Yong代对象一般比较少,所以采用复制的算法来回收内存,所以在每次垃圾回收时第二个survivor代区域就是用于保存Eden区和第一个Survivor区里面的可到达的对象,然后清空Eden区和Survivor区1。.
    2).Old代:经过多次垃圾回收依旧坚挺的存在Yong区可到达对象,将迁移到Old区。该区垃圾回收主要采用标记压缩算法。
    3).Permanent代:默认装载Class,方法等信息,默认64M,垃圾回收通常不处理这部分内存。
  • 常见的垃圾回收器:
    1.串行回收器
    2.并行回收器
    3.并行压缩回收器
    4.并发标记-清理回收器

内存管理小技巧:

  1. 尽量使用直接量,可以使用基本类型就不要使用对应的包装类,可以使用字符常量就不要new一个String。
  2. 字符拼接不要使用+,尽量使用StringBuilder和StringBuffer。
  3. 尽早释放无用对象,赋值null最为常见。
  4. 尽量少用静态变量。
  5. 避免在常用方法或循环中创建java对象。
  6. 缓存经常使用到的对象
  7. 尽量不要使用finalize方法,不要企图覆写finalize来实现清理资源,以免加重垃圾回收的开销
  8. 考虑使用软引用。

 

软引用实验代码:

 

弱引用实验源码:

 

虚引用实验源码:

 

内存泄露实验源码:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值