• Java对象不再使用时,为什么要赋值为 null ?
  • 发布于 1周前
  • 47 热度
    0 评论

问题:Java对象不再使用时,为什么要赋值为 null ?


原因是,便于JVM(虚拟机)回收。Java不像C++等其它语言,Java用好的对象是由JVM回收,即垃圾回收机制,也叫GC。在代码里,new的对象是放在JVM的堆区(即heap区),当然创建对象不止new,还有四种,这里不一一列举,但所创建的对象,只要不是static或常量,基本都放堆区。


同时,项目里,static静态变量和常量,所占据的空间不会多,所以一般意义的JVM内存管理,其实是针对new出来的对象,也就是说对堆区进行管理。

JVM如何判断堆区一个对象能否回收?看该对象上是否有强引用,一般new出来的对象叫强引用,除此之外,还有弱、软和虚引用,其它的用得不多,这里暂时不提。

比如String str = new String("123");,这里会在内存中开辟一块空间,该空间里存放123,该空间当下有个强引用,叫str,如果再外加一句,list.add(str);,那么这块空间上会有两个强引用,第一是str,第二是list加上的。

只要有一个强引用,该对象就不会被回收。如果有了这句话,list.clear();,那么包含123内容的空间上,本来有2个强引用,现在list的引用被撤销,只有一个str的引用,如果再加上str=null;,就相当于撤销了123内存上的另一个强引用,即该块内存上没有强引用,下次垃圾回收时,该块对象可以被释放。

再看下这个情况,String str = new String("123");,再有list.add(str);,如果只写了list.clear()或str=null,另一个不写,会有什么后果?包含123内容的内存块,上面有一个强引用,导致该内存块无法被JVM的垃圾回收流程回收。

有人会说,即然JVM会回收内存,那么早回收和晚回收差别不大,其实这话就错了。如果是跑一个main函数,该函数运行持续时间也就几秒,那么该程序结束后,JVM确实会回收其中的内存,此时早回收晚回收差别确实不大。

但很多Java项目,是上线后一直运行,直到一两个月后下次部署时,才会被终止,或者是,要等到一两周以后才会被重启。比如一些支付项目或电商项目就像这样。这种情况下,重启时确实会回收该段程序里用到的所有内存,但如果代码没写好,本来用好就回收的对象,一直不回收,积累起来,真可能把内存耗尽,从而导致线上问题,最直接的后果就是,系统再也无法获取内存,从而无法对外再提供服务。

所以,对象用好以后,应当尽早设置成null,目的是,减少该对象上的强引用,从而尽快让JVM回收该资源,类似的做法是,一个Connection或IO或Socket等物理对象,用好以后需要及时close,ArrayList或HashMap等集合对象,用好以后要尽快clear。

另外再多说一句,毕竟靠写代码或者是review代码,无法完全杜绝内存问题,所以当下不少系统,回在上线后用cat等组件监控,一旦内存用量高于80%,cat等组件就会发邮件告警,然后程序员得介入处理,总之,虽然JVM能自动回收内存,但写代码时,程序员也得注意别有内存泄露。
用户评论