搜索
首页Javajava教程JVM内存管理------杂谈(借此也论一论obj=null)

作为一个程序猿,修炼的过程就犹如玄幻小说中的主角,不仅需要练习各种武技,内气的修炼的一样重要。虽然武技可以迅速的提升主角的实力,但是在内气太差的情况下,根本发挥不出武技的十之一二。
因此,在介绍过设计模式这一类外功之后,LZ就直接转战内气修炼,和各位猿友探讨一下JVM的内容。
本来这一章应该是介绍与GC相关的内容,不过在此之前,LZ准备先和各位探讨一下一个编程的小技巧。当然,这个小技巧其实也是与GC密切相关的。
不知道各位猿友有没看过一些JAVA内存相关的文章,里面在罗列建议的时候,经常会写出这样一条建议。
第XX条、请在使用完对象之后,显示的将对象设置为null。
原话不一定如此,但意思是一样的。话里所描述的意思,就是说我们以后写代码应该这么写。

Object obj = new Object();  
//to do something   
obj = null;

这段代码有点C/C++的风格,obj=null代替了C/C++中的delete obj或者是free(obj),相当于在提示我们,就算有了GC,我们也要像没有GC一样,使用完对象就得将其赋为空值。
首先,LZ这里要说明的是,将obj赋为空值,与C/C++中的delete其实有着天壤之别,LZ之所以说它们代替了delete和free,仅仅是因为它们出现在代码中的位置类似而已。
obj=null只做了一件事,就是将obj这个引用变量与new Object()创造的实例的关联断开,实际上,实例所占用的内存空间依然没有释放。
在提出这个建议的时候,很多博主或者图书的作者(因为有不少博主估计也是从书上看的)的本意,是想尽快消除引用与实例的关联,从而诱发GC在进行垃圾回收时,将实例所占用的内存释放。在某些时候,这么做也是为了消除内存泄露。
LZ个人觉得,许多博主或者是图书作者,提出这个建议的初衷,主要是针对一些没有接触过GC原理以及内存管理的程序猿而建议的,因为在不明白相关知识的前提下,很容易掌握不好变量的作用域,从而导致不必要的内存浪费(个人觉得这个并不是主要目的,因为只要没有发生内存泄露,内存终究是要被GC释放的),甚至是内存泄露。
所以为了安全起见,有些高人们就提出了这么一个建议。
有鉴于此,LZ个人觉得,在各位掌握了相关知识之后,完全可以忽略这个建议,而且这么做明显会降低代码的清晰度以及增加编码的负担,然而所换来的好处,却只是为了避免那根本不一定存在的内存泄露。
这里解释一下为何在有些时候不将对象赋为空值会造成内存泄露,我们考虑下面一段代码。

import java.util.Arrays;  
public class Stack {  
      
    private static final int INIT_SIZE = 10;  
    private Object[] datas;  
      
    private int size;  
    public Stack() {  
        super();  
        datas = new Object[INIT_SIZE];  
    }  
      
    public void push(Object data){  
        if (size == datas.length) {  
            extend();  
        }  
        datas[size++] = data;  
    }  
      
    public Object pop(){  
        if (size == 0) {  
            throw new IndexOutOfBoundsException("size is zero");  
        }  
        return datas[--size];  
    }  
      
    private void extend(){  
        datas = Arrays.copyOf(datas, 2 * size + 1);  
    }  
      
}

这段代码是一个简单的长度可伸缩的栈实现,在你写一段测试代码去测试它的时候,会发现它毫无问题。但是不好意思,这里面就有一个明显的“内存泄露”,这就是因为一些对象或者说引用没有设置为空值所造成的。 
如果你还没看出来,LZ稍微提示一下,各位就会意识到了。这段代码里面,数组里的对象只会无限增长,而不会随着栈中元素的弹出而减少,减小的仅仅是对外展示的栈的大小size。考虑一个极端的场景,假设你曾经往栈中放入了100万个对象,最后使用了99万9千9百9十9个,从外部看来,栈中还只剩一个可用对象了,但是我们的栈依然持有着100万个对象的引用。如果JVM可以活过来的话,想必一定会把你蹂躏到死的。
我们缺少的就是将对象赋为null值的那一步,所以pop方法应该改为下面的方式,而且各位可以去看一下ArrayList中remove方法的源码,也是类似的思路。

public Object pop(){  
        if (size == 0) {  
            throw new IndexOutOfBoundsException("size is zero");  
        }  
        Object data = datas[--size];  
        datas[size] = null;  
        return data;  
    }

这个内存泄露是非常隐蔽的,而且实际使用当中不一定就能发现,因为随着Stack对象的回收,整个数组也会被回收,到时内存泄露就被掩盖了。
所以个人觉得上述的那个建议是完全没有必要的,就算遵从了上面的建议,如果对内存管理不熟悉的话,也不会想到上面这个代码中的问题。如果想彻底的避免内存泄露的发生,机械式的主动将对象赋为空值,并不是一个可以从根本上解决问题的办法。
真正能够解决问题的办法,就是掌握好GC的策略与原理,定义一个变量时多注意变量的作用域,如此才可以更好的避免内存泄露。
所以学好GC原理还是很有必要的,希望准备走JAVA之路的朋友,尤其是从培训机构出来的猿友们(此处没有鄙视培训机构出来的猿友们的意思,因为LZ本人也是半路出家,从培训机构走上编程之路的程序猿之一),一定不要只专注于各个框架的使用以及业务的深入,虽然这些事很有必要,但并不是全部。
follow me and go the memory world 吧(语法都是浮云)。

 以上就是JVM内存管理------杂谈(借此也论一论obj=null)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
在Java应用程序中缓解平台特定问题的策略是什么?在Java应用程序中缓解平台特定问题的策略是什么?May 01, 2025 am 12:20 AM

Java如何缓解平台特定的问题?Java通过JVM和标准库来实现平台无关性。1)使用字节码和JVM抽象操作系统差异;2)标准库提供跨平台API,如Paths类处理文件路径,Charset类处理字符编码;3)实际项目中使用配置文件和多平台测试来优化和调试。

Java的平台独立性与微服务体系结构之间有什么关系?Java的平台独立性与微服务体系结构之间有什么关系?May 01, 2025 am 12:16 AM

java'splatformentenceenhancesenhancesmicroservicesharchitecture byferingDeploymentFlexible,一致性,可伸缩性和便携性。1)DeploymentFlexibilityAllowsibilityAllowsOllowsOllowSorlowsOllowsOllowsOllowSeStorunonAnyPlatformwithajvM.2)penterencyCrossServAccAcrossServAcrossServiCessImplifififiesDeevelopmentandeDe

GRAALVM与Java的平台独立目标有何关系?GRAALVM与Java的平台独立目标有何关系?May 01, 2025 am 12:14 AM

GraalVM通过三种方式增强了Java的平台独立性:1.跨语言互操作,允许Java与其他语言无缝互操作;2.独立的运行时环境,通过GraalVMNativeImage将Java程序编译成本地可执行文件;3.性能优化,Graal编译器生成高效的机器码,提升Java程序的性能和一致性。

您如何测试Java应用程序的平台兼容性?您如何测试Java应用程序的平台兼容性?May 01, 2025 am 12:09 AM

效率testjavaapplicationsforplatformcompatibility oftheSesteps:1)setUpautomatedTestingTestingActingAcrossMultPlatFormSusingCitoolSlikeSlikeJenkinSorgithUbactions.2)contuctualtemualtemalualTesteTESTENRETESTINGINREALHARTWARETOLEALHARDOELHARDOLEATOCATCHISSUSESUSEUSENINCIENVIRENTMENTS.3)schictcross.3)schoscross.3)

Java编译器(Javac)在实现平台独立性中的作用是什么?Java编译器(Javac)在实现平台独立性中的作用是什么?May 01, 2025 am 12:06 AM

Java编译器通过将源代码转换为平台无关的字节码,实现了Java的平台独立性,使得Java程序可以在任何安装了JVM的操作系统上运行。

在平台独立性的平台独立性上使用字节码优于本机代码的优点是什么?在平台独立性的平台独立性上使用字节码优于本机代码的优点是什么?Apr 30, 2025 am 12:24 AM

ByteCodeachievesPlatFormIndenceByByByByByByExecutedBoviratualMachine(VM),允许CodetorunonanyplatformwithTheApprepreprepvm.Forexample,Javabytecodecodecodecodecanrunonanydevicewithajvm

Java真的100%独立于平台吗?为什么或为什么不呢?Java真的100%独立于平台吗?为什么或为什么不呢?Apr 30, 2025 am 12:18 AM

Java不能做到100%的平台独立性,但其平台独立性通过JVM和字节码实现,确保代码在不同平台上运行。具体实现包括:1.编译成字节码;2.JVM的解释执行;3.标准库的一致性。然而,JVM实现差异、操作系统和硬件差异以及第三方库的兼容性可能影响其平台独立性。

Java的平台独立性如何支持代码可维护性?Java的平台独立性如何支持代码可维护性?Apr 30, 2025 am 12:15 AM

Java通过“一次编写,到处运行”实现平台独立性,提升代码可维护性:1.代码重用性高,减少重复开发;2.维护成本低,只需一处修改;3.团队协作效率高,方便知识共享。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具