public class People {
private String name;
private int age;
private Info info;

public static void main() {
People p = new People(); //当运行完这句的时候内存的分配情况
}
}
class Info {

}
自己画的图,非常不标准。谁能给我解释下。今天突然想到的。

解决方案 »

  1.   

    不好意思。上面代码着急,忘创建Info对象了。
    public class People {
        private String name;
        private int age;
        private Info info = new Info();    
        public static void main(String[] args) {
            People p = new People(); //当运行完这句的时候内存的分配情况
        }
    }
    class Info {
        
    }
      

  2.   

    1楼那种情况,应该是不对的。你想想,假如是多线程。每个线程有自己的栈。对象是线程共享的(因为存放在堆中)。那你对象中的info存的是哪个线程中栈p.info的地址?肯定不能存。所以,不是所有的引用都存放在栈中吧?或者是别的模型?
      

  3.   

    哪个线程中p.info的地址都一样,所以可以存在栈中的。
      

  4.   

    栈中只有一个p的引用,应该不是1楼的情况。你想,如果你那个Info类不是一个简单的类,而还有数据元素,如下面这种情况:
    class Info{
    String s = new String();
    Info i = new Info();
    }那p.info.s和p.info.i又放哪里呢,或者p.info.i.i.i.i.i...这种情况又如何考虑?
      

  5.   

    楼主发的帖子图是正确的。很多人所谓“引用分配在栈中”是这样说的“引用分配在栈中,对象分配在堆中”,p.Info是对象的一部分,自然是在堆中。注意表达环境。
      

  6.   


    您能不随口一说吗?说说,他是怎么实现的呗?虚拟机为每个线程分配了虚拟机栈。而每个方法的调用,相当于栈帧入栈出栈的过程。栈桢中有局部变量表(也就是我们平时说的栈,我们平时说的并不是非常准确)。你的意思是,这个p.info在每个栈帧中的位置都一样?那太牛了。怎么做到的呢?他做不到,做到代价太大了。你想想每个方法的变量都不一样,他怎么保证p.info在栈帧的地址都一样。而且,如果不放在堆里,而是像你说的那样。他根本就不知道上一个方法中的p.info在栈帧中的地址。因为上一个方法的已经执行完了,栈帧都出栈了。加上多线程,你就更不行了。如果是别的实现,能给小弟解释一下吗?
      

  7.   

    楼主,我认为你顶帖里面说的是对的,引用别处的一句话:堆中存的是对象,栈中存的是基本数据类型和堆中对象的引用。一个对象的大小是不可估计的,或者说是可以动态变化的,但是在栈中,一个对象只对应了一个4btye的引用(堆栈分离的好处)这里的解释我认为比较清楚,可参见:
    http://developer.51cto.com/art/200911/165015.htm
    至于你说“对,那如果有人说,引用都分配在栈中就错了呗?”这句话完全要看这句话的背景,因为一般人都是将线程作为背景在讨论的,如果你把线程这个范围界定进来,那我认为这句话就没啥错误;而一个对象中包含另一个对象,显然不在这之列。
      

  8.   


    你说的意思,感觉和ldh911非常像。您同意顶楼的图吗?
      

  9.   

    堆和栈,都是运行时的数据结构。
    不能静态的去理解。
    我不是说了吗 ? 栈里保存的是当前的上下文环境,
    你的函数,当前访问某个对象的引用,那么,栈里就有哪个对象的引用,不访问,就没有。当你的函数,即访问了p对象,又访问了p.info对象,那么,栈里就有两个引用。但是,p对象内部的info变量,始终指向对应的Info对象,而不是栈。
      

  10.   


    先声明一下,我是动态理解的。你说的我看懂了,跟我想的是一样的。我讨论的是,是不是所有引用都在栈里面(堆里有没有对象引用)。而不是这个栈里面有没有这个对象的引用。但是,p对象内部的info变量,始终指向对应的Info对象,而不是栈。有你上面这句话就够了。就说明了,p对象实例中的info变量。确实是个引用类型的变量。感谢,您的耐心解答。
      

  11.   

    堆上 第一个地址是 Main()这个方法的,people没new怎么会分配
    静态方法和类加载管理都是在另外区域的 
      

  12.   


    别在这装大爪子,看好了上面怎么说的。告诉你静态方法和类加载也在堆里。只不过是堆里的方法区。看看有关JVM的书,再来装。
      

  13.   

    我认为应该是第二种方法正确public class People {
    private People p = new People();
    public static void main(String[] args) {
    People p = new People();
    }
    }
    以上代码,运行后的结果是java.lang.StackOverflowError
    如果按LZ第一张图,那为何是栈溢出而不是堆溢出呢?
      

  14.   

    我的观点是,引用、方法、8大封装类都是存在栈里的。
    new出来的对象存在堆内。如果是内置对象他的引用仍然是在栈里。
      

  15.   


    你这个说法就更搞笑了。看看JVM的书,当程序要申请的虚拟栈大小过大。就会溢出。你无限递归,函数自己也占空间。当然栈溢出。跟引用在哪无关,下面的函数也栈溢出。没有啥引用。你那个逻辑不通
    public class Test{
    public static void main(String[] args) {
    new People().h();
    }
    }
    class People{
    public void h(){
    h();
    }
    }