前段时间学习二叉树在处理删除操作的时候遇到一个头疼的问题:删除节点的时候明明已经置null了可树上该节点依旧存在,还必须执行node.father.left = null;才可以删除node节点,寻找了一下原因发现还是因为对java内存管理理解不够深入。

代码如下:

	@Test
public void testNode() {
Node node1 = new Node("node1");
Node node2 = new Node("node2");
node2.father = node1;
node1.next = node2;
changeNode(node1.next);
System.out.println(node1.next.name);
} private void changeNode(Node node3) {
node3 = null;
}

  运行代码之后发现本来已经在changeNode()中已经设置node3 = null;可依旧能输出 node1.next.name。

要知为何?先理解几个概念:

  1、栈内存存储基本类型的变量对象的引用变量。
  2、堆内存用于存放由new创建的对象和数组。每new一个对象就在堆内存中开辟一个新的存储空间存储此实例对象。
  3、Person p = new Person();
    执行new命令时程序执行两步:a:在堆内存中开辟一段空间,存储new出来的对象;b:在栈内存中添加一个变量p,p中存放的是该对象在堆内存中开始存放处的物理地址。
  4、p = null;
    执行此步骤的时候程序只是更改栈内存中的P变量所保存的地址,把地址指向null,而并没有操作堆内存(把p所指向的对象实例清空回收)。
  5、无论是形参或者实参,执行 XXX = null;操作时都是把XXX变量栈中存储的地址改为指向null的地址。不操作堆中的数据。

下面就分析一下每步代码在堆内存和栈内存中的变化:

  1、当new一个对象的时候,程序首先在堆内存中开辟一段空间实例化对象,同时在在栈内存中加入一个node1的变量,此变量中保存的是堆内存中物理地址的首地址。

  

2、当调用方法传入参数的时候,在栈内存中添加一个局部变量node3,存储node2的物理首地址。也即是把node2的值0X00011拷贝进node3的栈内存中。

有网友说这是引用传递,其实传递的还是值,只不过node2的值本来就是物理地址,然后把这个物理地址值传给node3.

3、当执行node3 = null; 的时候,程序会把node3中的0X00011变为一个指向null的地址 0Xaaaaa.但是程序不对堆内存中数据进行管理(堆内存中没有引用指向的数据会在一定的时间通过GC进行处理)。

可以看到执行到此步只是把变量中的物理地址置空,但并没有删除node2在堆内存中的数据,这正是为什么删除之后节点之后原数据依旧存在的原因。可以看到node1中的next依旧指向0X00011。

即使执行node2 = null,程序依旧不改变堆内存。

原数据依旧存在!

JVM内存处理实际情况要远远比这复杂得多,如果想深入了解可以找找 jvm内存处理机制相关资料,网上一搜一大堆,不再赘述。其实我也不知道。

  

java堆内存和栈内存的处理的更多相关文章

  1. Java堆空间Vs栈内存

    之前我写了几篇有关Java垃圾收集的文章之后,我收到了很多电子邮件,请求解释Java堆空间,Java栈内存,Java中的内存分配以及它们之间的区别. 您可能在Java,Java EE书籍和教程中看到很 ...

  2. JAVA内存管理之堆内存和栈内存

    我们常常做的是将Java内存区域简单的划分为两种:堆内存和栈内存.这种划分比较粗粒度,这种划分是着眼于我们最关注的.与对象内存分配密切相关的两类内存域.其中栈内存指的是虚拟机栈,堆内存指的是java堆 ...

  3. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

  4. java堆内存与栈内存

    java的内存分为两种,堆内存与栈内存: 堆内存用来存放数组和new的对象,比如一个文件,字节流是存放在堆中,栈内存为这个文件开辟一个索引,也就是这个文件的地址,并且保存在栈中.对象由GC处理释放内存 ...

  5. 熟悉java堆内存和栈内存和mysql的insert语句中含有id的处理

    java的堆内存和栈内存有什么区别呢? 如果mysql数据库表的id是递增的,如果没有插入id,则id自增,如果插入id,则插入什么就显示什么.

  6. 浅析JAVA中堆内存与栈内存的区别

    Java把内存划分成两种:一种是栈内存,一种是堆内存. 一.栈内存 存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则.     栈内存在函数中定义的“一些基本类型的变量和对象的引用变量”都 ...

  7. Java SE之Java中堆内存和栈内存[转/摘]

    [转/摘]1-3Java中堆内存和栈内存 注解:内存(Memory)即 内存储器,主存,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器(辅存)交换的数据. Java中把内存分为两种:栈 ...

  8. JAVA堆内存和栈内存初步了解

    一.堆内存和栈内存 程序运行时内存分配有三种:静态存储分配,栈式存储分配,堆式存储分配 1.静态存储分配: 在程序编译时就可以确定数据目标在运行时所需要的内存,因此在编译时就为其分配固定大小的内存. ...

  9. Java 堆内存和栈内存

    看了一些别人总结的博客,感觉对堆内存和栈内存有了一个初步的认识.所以来写写自己对堆内存和栈内存的理解. Java把内存分成两种,一种叫做栈内存,一种叫做堆内存. 在函数中定义的一些基本类型的变量和对象 ...

随机推荐

  1. cocos2d-x 开头配置(Windows 平台)

    工欲善其事,必先利其器. 要使用 cocos2d-x 引擎,就要配置(或者安装)引擎,到 cocos2d-x 官网下载页下载引擎,官网给了2.x和3.x两个版本,我使用的是3.6的版本,3.x的版本类 ...

  2. Linux 环境变量配置

    linux 环境,用户通过shell 操作时,系统会为用户初使化环境变量, 比如系统公共资源路径: path , include , bin 等目录. shell 模式下,执行 export , 查看 ...

  3. IDE启动报错

    启动IDE的时候报出org.eclipse.swt.SWTException: Invalid thread access解决方法:退出再次启动IDE的时候加上-clean选项,如图中所示,前面是我的 ...

  4. Android SQLiteOpenHelper(一)

    SQLiteOpenHelper api解释: A helper class to manage database creation and version management. You creat ...

  5. springmvc 向页面传值

  6. iOS学习之GCD

    多线程编程 线程定义:一个CPU执行的CPU命令 列一条无分叉的路径就叫线程. 多线程:执行多个不同的CPU命令 有多条路径. 线程的使用:主线程(又叫作UI线程)主要任务是处理UI事件,显示和刷新U ...

  7. 苹果IPhone手机由于更新了IOS7 Beta测试版导致“激活出错”后,如何还原电话本和照片方法

    苹果这狗日的,手段果然狠,因为用户提前升级了测试版又没有更新正式版,就突然把手机变砖头,既不让升级正式版,也不让备份手机中的信息,确实有必要这样吗? 我的手机是IPone4s,在看了6月Apple W ...

  8. 表单验证 jQuery Validate

    http://www.runoob.com/jquery/jquery-plugin-validate.html http://www.cnblogs.com/linjiqin/p/3431835.h ...

  9. fastcoloredtextbox控件 看下是否解决了中文

    该控件解决中文网址     未测试是否解决   想保存 http://www.dullong.com/share-a-code-can-be-highlighted-components-fastco ...

  10. Day20_IO第二天

    1.IO体系总图 2.IO体系--字节流 记忆路线:输入输出流前面加File和Buffered,这样就全记住了 3.表达式解释 表达式:由变量和常量通过运算符连接起来的式子,单个的常量和变量也是表达式 ...