zoukankan      html  css  js  c++  java
  • java十分钟速懂知识点——引用

    一、由健忘症引起的问题

        今天闲来没事在日志中瞟见了个OutOfMemoryError错误,不由得想到前一段时间看到一篇面经里问到Java中是否有内存泄露,这个很久以前是留意过的,大体记得内存溢出和内存泄露是不同的,至于各自都有哪些情况,那个...额....忘了...。好吧,记忆力一向不好,忘就忘了,那就再总结一遍吧。翻了下收藏的博客,回顾了下便是想起了了~.~。看起来一切很美好,但是其中的一个例子突然使我困惑了:

    public class TestDemo {
        static Test[] tests = new Test[3];
    
        public static void main(String[] args) {
            Test t = new Test("test1");
            tests[0] = t;
    
            //将t置为null,看起来似乎我们已经释放创建的对象,当下次gc时其将被回收
            t = null;
    
            //那么我们打印下test[0]看看
            System.out.println(tests[0]);
        }
    }

        这是个示例内存泄露的例子,该例子十分典型,几乎所有内存泄露的示例都与此类似,作为javaer往往觉得理所应当。然而作为一个学习C++入行(学的很烂),并一直把引用当指针看的javaer不免觉得有些疑惑:t是对象的引用,这里可以看做指向对象的指针,那么test[0]=t,按理说应该是把t指针赋值给test[0],算是地址传递吧,那个t指向null之后,test[0]应该也指向null了啊。
        看起来似乎有点道理,然而当了解了java的引用之后,发现吧指针等同于引用是有一些问题的。

    二、引用到底是什么

        java中的引用到底是什么呢,简单点说,引用就是存在栈区的一种特定类型的数据,其存储着对象实例在堆区的地址,其特点如下:

    • 本身是一种数据类型,存储在栈区
    • 其值存储着实例对象在堆区的虚拟地址(注意,是虚拟地址,并不是实际内存地址,就如同图书馆里的索引号,不经过转换你并不知道书的实际位置
    • 对象在创建未赋值时(无实例),引用会指向null
    • java中参数传递只有值传递一种,所谓的引用传递传递的是引用中存储的值

        从定义看起来似乎还是区分不出来引用到底和指针有什么区别,那么请注意上边红字,java为了屏蔽对内存直接操作,对对象的实际内存地址进行了包装,从而使引用中的值只能用来找对象,而无法操作内存。这一点正是和指最大不同,C++中的指针就是一个真实的内存地址,可以通过该地址把内存玩出十八般花样。这点也说明了我们常常把引用传递当成地址传递是错误的(虽说实际效果差不多)。

    三、上边的例子到底发生了什么

        好吧,看了上边一坨也许你并看不出个什么,也许本身这块有点绕,也许我说的不清楚,那么我们不如直接画图说明上边那个例子到底发生了什么(图示画的不一定和实际完全一致,只为说明问题),说不定你就明白了:
        tests由于是静态变量,在类加载完就已经实例化了,其在堆内存中分配了长度为3的空间,不过值都为null。在创建t之后,t指向了堆内存中的对象:


        tests[0]=t,这就是我们理解错误的地方,这一步test[0]并不是指向t,而是t把Test实例的地址直接赋值给了tests[0],因此tests[0]同样指向Test实例,这和t已经没有任何关系了。

        其实从上图我们就应该理解了,t=null之后,其实只是斩断了t和Test实例的关系,并没有改变Test到tests的依赖,从而gc并不会回收Test,这样就造成了逻辑上的内存泄露(为啥说逻辑上,因为明明就是你让tests还存着Test呢,只是你自以为是的以为释放了,当然,这种意义的泄露和C++所说的内存泄露很不同)。

    四、只为了结尾不突兀

        本来是想整理篇内存溢出和内存泄露的,顺便写下这块,但是发现并不是太好说清楚,就单写了。好了,就这样吧,原来JVM学习总结系列写了一半扔那了,现在发现还是挺有意思的,有空接着写吧。



  • 相关阅读:
    饿了么P7级前端工程师进入大厂的面试经验
    前端程序员面试的坑,简历写上这一条信息会被虐死!
    这次来分享前端的九条bug吧
    移动端开发必会出现的问题和解决方案
    创建一个dynamics 365 CRM online plugin (八)
    创建一个dynamics 365 CRM online plugin (七)
    创建一个dynamics 365 CRM online plugin (六)
    创建一个dynamics 365 CRM online plugin (五)
    使用User Primary Email作为GUID的问题
    怎样Debug Dynamics 365 CRM Plugin
  • 原文地址:https://www.cnblogs.com/good-temper/p/4916063.html
Copyright © 2011-2022 走看看