不好意思。上面代码着急,忘创建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 {
栈中只有一个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...这种情况又如何考虑?
我认为应该是第二种方法正确public class People { private People p = new People(); public static void main(String[] args) { People p = new People(); } } 以上代码,运行后的结果是java.lang.StackOverflowError 如果按LZ第一张图,那为何是栈溢出而不是堆溢出呢?
你这个说法就更搞笑了。看看JVM的书,当程序要申请的虚拟栈大小过大。就会溢出。你无限递归,函数自己也占空间。当然栈溢出。跟引用在哪无关,下面的函数也栈溢出。没有啥引用。你那个逻辑不通 public class Test{ public static void main(String[] args) { new People().h(); } } class People{ public void h(){ h(); } }
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 {
}
class Info{
String s = new String();
Info i = new Info();
}那p.info.s和p.info.i又放哪里呢,或者p.info.i.i.i.i.i...这种情况又如何考虑?
您能不随口一说吗?说说,他是怎么实现的呗?虚拟机为每个线程分配了虚拟机栈。而每个方法的调用,相当于栈帧入栈出栈的过程。栈桢中有局部变量表(也就是我们平时说的栈,我们平时说的并不是非常准确)。你的意思是,这个p.info在每个栈帧中的位置都一样?那太牛了。怎么做到的呢?他做不到,做到代价太大了。你想想每个方法的变量都不一样,他怎么保证p.info在栈帧的地址都一样。而且,如果不放在堆里,而是像你说的那样。他根本就不知道上一个方法中的p.info在栈帧中的地址。因为上一个方法的已经执行完了,栈帧都出栈了。加上多线程,你就更不行了。如果是别的实现,能给小弟解释一下吗?
http://developer.51cto.com/art/200911/165015.htm
至于你说“对,那如果有人说,引用都分配在栈中就错了呗?”这句话完全要看这句话的背景,因为一般人都是将线程作为背景在讨论的,如果你把线程这个范围界定进来,那我认为这句话就没啥错误;而一个对象中包含另一个对象,显然不在这之列。
你说的意思,感觉和ldh911非常像。您同意顶楼的图吗?
不能静态的去理解。
我不是说了吗 ? 栈里保存的是当前的上下文环境,
你的函数,当前访问某个对象的引用,那么,栈里就有哪个对象的引用,不访问,就没有。当你的函数,即访问了p对象,又访问了p.info对象,那么,栈里就有两个引用。但是,p对象内部的info变量,始终指向对应的Info对象,而不是栈。
先声明一下,我是动态理解的。你说的我看懂了,跟我想的是一样的。我讨论的是,是不是所有引用都在栈里面(堆里有没有对象引用)。而不是这个栈里面有没有这个对象的引用。但是,p对象内部的info变量,始终指向对应的Info对象,而不是栈。有你上面这句话就够了。就说明了,p对象实例中的info变量。确实是个引用类型的变量。感谢,您的耐心解答。
静态方法和类加载管理都是在另外区域的
别在这装大爪子,看好了上面怎么说的。告诉你静态方法和类加载也在堆里。只不过是堆里的方法区。看看有关JVM的书,再来装。
private People p = new People();
public static void main(String[] args) {
People p = new People();
}
}
以上代码,运行后的结果是java.lang.StackOverflowError
如果按LZ第一张图,那为何是栈溢出而不是堆溢出呢?
new出来的对象存在堆内。如果是内置对象他的引用仍然是在栈里。
你这个说法就更搞笑了。看看JVM的书,当程序要申请的虚拟栈大小过大。就会溢出。你无限递归,函数自己也占空间。当然栈溢出。跟引用在哪无关,下面的函数也栈溢出。没有啥引用。你那个逻辑不通
public class Test{
public static void main(String[] args) {
new People().h();
}
}
class People{
public void h(){
h();
}
}