String a = "abc"; String b = "abc"; System.out.println(a==b); 结果为true 这就说明了a b其实指向同一个值 注意,我们这里并不用a.equals(b);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,a与b是否都指向了同一个对象。 结果说明,JVM创建了两个引用a和b,但只创建了一个对象,而且两个引用都指向了这个对象。首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有abc这个值,如果没找到,就将abc存放进来,然后将a指向abc。接着处理String b = "abc";在创建完b的引用变量后,因为在栈中已经有abc这个值,便将b直接指向abc。这样,就出现了a与b同时指向abc 特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与b的值后,再令a=abcd;那么,b不会等于abcd,还是等于abc。在编译器内部,遇到a= abcd;时,它就会重新搜索栈中是否有abcd的字面值,如果没有,重新开辟地址存放abcd的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。 堆内存: 堆内存用来存放所有new 创建的对象和 数组的数据、 String a = new String ("abc"); String b = "abc"; System.out.println(a==b); //False String a = new String ("abc"); String b = new String ("abc"); System.out.println(a==b); //False创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
堆空间 就是用来存储对象的
栈空间是用来存储一些变量的 用完后会通过垃圾收集器自动清楚
引用对象通过类似指针的方法来指
程序从硬盘载入的内存->有四个内存区供程序使用
heap(堆 ),stack(栈),data segment,code segment
heap堆:用来存放new出来的东西
stack栈:局部变量。
data segment:静态变量,字符串常量。
code segment:存放代码
回楼主,首先解释一下虚拟机内存:
java虚拟机存在方法区,堆空间与栈空间,定义是这样的,虚拟机具体实现完全可以把它们分开在不同内存中,也可以把它们放在同一段内存中。
方法区存放类与方法。
堆空间存放实例化的对象。
栈空间有两种,一种是方法栈,虚拟机会为每个线程所调用的方法申请空间,而这个栈就是这些空间,另外一个是操作数栈,两个局部变量或者成员变量需要进行处理的时候,执行语句会吧这两个变量的值放入操作数栈中进行处理,处理完成以后会将处理结果弹出栈。
了解了这些后其实那些问题都不难:
第一个问题上面说得很清楚了。
第二个问题,当虚拟机生产对象的时候会申请内存空间(怎么申请的,你去看汇编程序设计以及寄存器寻址方式),然后如果引用是静态成员变量,则引用放在方法区中,如果引用是成员变量则放在堆中,如果引用是局部变量,则成为局部变量索引(局部变量没有变量名称,它只是一个索引项)。
第三个问题,虚拟机规范没有规定引用应该去怎么实现,如今应用大致有两种实现方式,一种是引用直接就是一个指向堆内存的指针,另外一个是引用指向方法区类对象映射表中的某个项,映射表中的项再以指针的形式指向堆内存空间,具体实现可能还有更多情况,所以这个问题你不必太过于探讨。
总结了下:有些是根据网上总结的(由于时间的问题,还没结完)
有错的地方希望提出 毕竟我也是新手 总结不好的地方不要拍砖!
栈内存:
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 栈内存主要存放的是基本类型类型的数据 如、( int, short, long, byte, float, double, boolean, char) 和对象句柄。并没有有String基本类型、在栈内存的数据的大小及生存周期是必须确定的、其优点是寄存速度快、、栈数据可以共享、缺点是数据固定、不够灵活。 栈的共享:
String a = "abc";
String b = "abc";
System.out.println(a==b);
结果为true 这就说明了a b其实指向同一个值
注意,我们这里并不用a.equals(b);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,a与b是否都指向了同一个对象。
结果说明,JVM创建了两个引用a和b,但只创建了一个对象,而且两个引用都指向了这个对象。首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有abc这个值,如果没找到,就将abc存放进来,然后将a指向abc。接着处理String b = "abc";在创建完b的引用变量后,因为在栈中已经有abc这个值,便将b直接指向abc。这样,就出现了a与b同时指向abc
特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与b的值后,再令a=abcd;那么,b不会等于abcd,还是等于abc。在编译器内部,遇到a= abcd;时,它就会重新搜索栈中是否有abcd的字面值,如果没有,重新开辟地址存放abcd的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。
堆内存:
堆内存用来存放所有new 创建的对象和 数组的数据、 String a = new String ("abc");
String b = "abc";
System.out.println(a==b); //False
String a = new String ("abc");
String b = new String ("abc");
System.out.println(a==b); //False创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
在函数中定义的基本类型的变量和对象的引用变量都在函数的栈内存中分配、
堆内存用来存放由 new 、 newarray 、 anewarray 和 multianewarray 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。找找尚学堂、马士兵、张孝祥的视频看看就懂了
堆空间heap存放new出来的东西
通俗,呵呵
可怎么就没人看呢?
楼主去看《Thinking in java》的第二章 “一切都是对象”具体多少页不清楚了
肯定很详细,我曾经看过
在不懂,你拿到砍我。(在砍我的时候要想想砍是犯法的。。嘿嘿..)
0 ldc <String "abc"> [16]
2 astore_1 [aString]
3 ldc <String "abc"> [16]
5 astore_2 [bString]
6 returnjavac对.java文件进行处理,最后生成Class文件的字节码表示时,会同时生成一个常量池结构。在将数据放入常量池时,会对重复的数据进行过滤(其实是一个Map),保证值保存一份。
其实他是放在常量池里面的,而不是栈里面
特别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与b的值后,再令a=abcd;那么,b不会等于abcd,还是等于abc。在编译器内部,遇到a= abcd;时,它就会重新搜索栈中是否有abcd的字面值,如果没有,重新开辟地址存放abcd的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。 堆内存: 堆内存用来存放所有new 创建的对象和 数组的数据、 String a = new String ("abc"); String b = "abc"; System.out.println(a==b); //False String a = new String ("abc"); String b = new String ("abc"); System.out.println(a==b); //False 创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
6楼的说法基本上是对的,而且深有同感,部分中国人的书都是你抄我的,我抄你的,结果误导了一大批人,但也不是不要看中国人写得书,我觉得侯捷写的书就很好,最后推荐楼主看看《Java虚拟机规范》和《深入Java虚拟机》
web 网站建设
堆(heap):Class ,Array
当对象你把他NEW出来的时候 JVM就内存当中开辟了一块空间 这块空间就叫做堆 ,所有NEW出来的东西都放在堆里面
什么是栈 ?
除了NEW出来的东西 其他的放到栈里面
推荐资源下载:http://download.csdn.net/detail/qmx_zhq/3410905
堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
1、栈是分配内存地址,而堆空间是分配内存,有栈指向堆空间里面的对象