日期:2014-05-20  浏览次数:20676 次

关于内存分配的新人问题,请指点
1 void method1() {
  2 StringBuffer x = new StringBuffer("Hello");
  3 change1(x);
  4 System.out.println(x);
  5 }
  6
  7 void method2() {
  8 StringBuffer x = new StringBuffer("Hello");
  9 change2(x);
  10 System.out.println(x);
  11 }
  12
  13 void change1(StringBuffer sb) {
  14 sb.append(" world!");
  15 }
  16
  17 void change2(StringBuffer sb) {
  18 sb = new StringBuffer("hi");
  19 sb.append(" world!");
  20 }

执行18行,这里就出现了类似传入值拷贝的变化:new 方法并没有改变sb指向内存的内容,而是在内从中开辟了一块新的空间存放串"hi",同时sb指向了这块空间

第一个问题:第18行是否是先在堆,也就是String对象池中创建了一个“hi”,然后根据“hi”的具体内存地址,将一个已确定的值写入栈,然后将该地址值与String sb对应??在这里地址值是由对象在堆中的物理地址决定,而不是随便标记的??


第二个问题:基础数据变量int在内存中是直接写入栈中的,是否是以 “变量名:变量值 ”的方式写入的,而String变量实际上也是一致的,以“变量名:地址值”的方式???


1 String sb1="sb"
2 String sb2="sb"
第三个问题:在执行第二行时,是否是首先在String对象池中发现了“sb”,然后直接在栈中创建了一个“变量名:(原第一行)地址值”??对于sb1 sb2来说,在栈中相同的是地址值,不同的是和地址值写在一起的变量名??

------解决方案--------------------
真的想深入了解请阅读 深入java虚拟机 第二版
------解决方案--------------------
1
先在String常量池查找有没有hi,无则在常量池中创建hi,然后用hi对象作为参数,在堆中创建一个StringBuffer对象,并让sb指向该对象

2
变量有自己的内存空间,在栈中,变量的内存空间保存变量的值,对于基本类型,变量的内存空间保存的是基本类型的值,对于对象类型,变量的内存空间保存的是对象的地址

3
变量在编译的时候就被编译为栈中的相对地址,执行到第二行时,在池中找到sb,然后把sb的地址保存到sb2变量的内存地址中,对于sb1 sb2来说,它们是不同的两个变量,也就是它们在栈中地址是不同的,但是他们都引用同一个常量池的对象,也就是sb1 sb2的内存中保存的是相同的信息,即保存的是同一个对象的内存地址