java 内存管理详细解析

当你去问C++开发的人员,C++中什么让你感到最头痛。我想他们肯定会回答你,内存管理。java为了减轻程序员的负担。最终采用了垃圾收集的机制来实现内存的管理。我将从如下几个方面讲解:

一,对象在什么情况下成为垃圾

二,垃圾收集器

三,finalize详解以及最终守护者模式

四。三种特殊引用

一。对象在什么情况下成为垃圾

  1. 对于非线程对象来说,所有活动线程都不能访问该对象。该对象就成为了垃圾

  2。对于线程对象来说,满足第一个条件,并且线程还没启动或者死亡。

  这是两个概念。也许你觉得有点晕,接下来,我配合代码来详细解析。

 

  对于非线程对象而言有两种现象,一个事单对象,另外一个是多对象孤岛。

 

   1 在单对象情况下,一句话,指向特定对象的引用不再指向该对象。达到这个目的有方法三种:

   (1)特定对象的引用置空,Object a=new Object ();a=null

   (2)引用指向另外的对象

   (3)方法体结束,该方法的局部变量成为垃圾。

 

   2 多对象孤岛,直接上代码

   class Iland{

     Iland friend;

     }

    

  public class test{

 

 public static void main(String []sg){

  Iland one=new Iland();

  Iland two=new Iland();

  Iland three=new Iland();

  one.friend=two;

   tow.friend=three;

  three.friend=one;

  one=null;

  two=null;

  three=null;

}

}

 如果按照我们想象的思维来推理的话,这三个对象头尾相连,形成了一个三角形。那么应该有引用指向它们。实际上,三个对象都已经成为垃圾。因为没有任何活动线程来引用孤岛中的任何一个对象了。

 

对于线程对象满足了第一个条件后,并且线程没有启动或者死亡。上代码,请读者自己也琢磨一下,不要等着从天上掉知识。

 Class A extends {

  public void finalize(){

     System.out.prinlnt("对A进行垃圾收集");

 }

  public void run(){

   try{

    System.out.prinlnt("A 开始沉睡");

     Thread.sleep(100);

    System.out.prinlnt("A 苏醒,执行完毕");

 

   }catch(Exception e){e.printStackTrace();}

}

}

 

public class Test{

  public static void main(String []gs){

   A a=new A();

   a.start();

   a=null;

 

    System.gc()  ;

    System.out.prinlnt("开始进行垃圾收集");

    try{

     Thread.sleep(200);

    }catch(Exception e){e.printStackTrace();}

    }

 

  System.gc();

}

 在A线程启动后,即将a对象变为null。而此时a线程仍在执行中,所以此时a  不是垃圾。所以如果马上进行垃圾收集,不会收集a.等 a线程执行完毕, a成为垃圾可收集了。

二,垃圾收集器

  垃圾收集器是一个后台守护线程(至于什么是后台守护线程,你可以参阅其它资料,我在后面也会讲到).在内存充足的情况下,其优先级很低,但是当垃圾充斥的时候。其优先级会提高。由此可见,垃圾收集器什么时候工作我们是控制不了的。只是我们可以申请垃圾收集。申请垃圾收集有两个方法。

  1.RunTime 类。

  (1)public static RunTime getRunTime() 。它的构造器是private的,所以通过此方法获取它的对象。

  (2)public void gc()申请收集垃圾

   (3)public long totalMemory()返回当前JVM使用的总内存,单位是字节。

   (4)public long freeMemory()返回但前JVM空闲内存,单位字节

 

 2 System

  方法 public static void gc()

 

三,finalize详解以及最终守护者模式

  C++中要求程序员编写析构函数实现对内存的释放。在JAVA中通过finalize是程序在结束前进行必要的清理工作。jvm先调用此方法,然后清除该“垃圾对象”。以下是几个要注意的地方

  1 该方法属于Object类,任何类都继承了该方法

  2 其方法签名是 protect void finalize()throw Throwable

  3 需要执行的代码切不可以写在这里。

  4 在finalize 最好加上这样一句代码。super.finalize().因为有可能父类中要在次方法中执行一些清理工作。如果不这样,会造成意想不到的错误。

  5 finalize的安全问题。请看如下代码

  class A{

   static A a;

   public void finalize(){

    a=this;

  }

 

  }

  不知道你们看出什么问题来没有。每次在垃圾收集器收集该对象的时候,都会有一个类变量指向该对象,从而使得有引用指向该对象,结果避免了自己成为垃圾。但是最终结果却不是这样的。在java中finalize方法只执行一次。在第一次执行a的finalize 方法时a 挽救了自己,但是第二次执行时,java检测到该对象已经执行了一次finalize方法,故直接将该对象作为垃圾收集,不运行finalize方法。

 

6 最终守护者模式

 在子类的finalize方法中忘记super.finalize()是很危险的。有什么办法可以让我们不必在子类中调用父类的finalize方法呢?有,答案时最终守护者模式。代码如下:

class father{

 Object obj=new Object(){

  public void finalize() throws Throwable{

   System.out.println("最终守护者模式");

 }

 }

}

 

class son extends father{

 public void finalize(){

 System.out.println("子类finalize方法");

 }

}

 

public class Test {

 public static void main(String []gs){

  son s=new son();

  s=null;

  System.gc();

 }

}

 

 四:三类特殊的引用

   做学问,要学会这三个英文单词,what,why ,how。接下类我们带着这些疑问讲解如下问题。

1 。弱引用

  why: 我们为什么需要弱引用。

2. 。软引用

3 。幻影引用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值