一:java中怎么理解“堆空间”和“栈空间”?
二:还有实例化对象的时候是怎样开辟内存空间的?
三:引用对象内存怎么分配和指向?这些数据结构问题老是犯浑,平时都不没接触过,面试问到一句都说不出,请知道的朋友帮忙解释下。
能画个内存指向图更好....

解决方案 »

  1.   

    首先建议你看 尚学堂马士兵老师的 J2SE视频 主要看面向对象那章 通过画图 很快能理解这些
    堆空间 就是用来存储对象的
    栈空间是用来存储一些变量的 用完后会通过垃圾收集器自动清楚
    引用对象通过类似指针的方法来指
      

  2.   

    程序执行的过程
    程序从硬盘载入的内存->有四个内存区供程序使用
    heap(堆 ),stack(栈),data segment,code segment
    heap堆:用来存放new出来的东西
    stack栈:局部变量。
    data segment:静态变量,字符串常量。
    code segment:存放代码
      

  3.   

    首先回2楼,不要看中国人写得书,虽然中国文化源远流长,但是计算机这方面还是不要看中国人写的,毕竟有差距,而且中国人写的书很多都存在误导。
    回楼主,首先解释一下虚拟机内存:
    java虚拟机存在方法区,堆空间与栈空间,定义是这样的,虚拟机具体实现完全可以把它们分开在不同内存中,也可以把它们放在同一段内存中。
    方法区存放类与方法。
    堆空间存放实例化的对象。
    栈空间有两种,一种是方法栈,虚拟机会为每个线程所调用的方法申请空间,而这个栈就是这些空间,另外一个是操作数栈,两个局部变量或者成员变量需要进行处理的时候,执行语句会吧这两个变量的值放入操作数栈中进行处理,处理完成以后会将处理结果弹出栈。
    了解了这些后其实那些问题都不难:
    第一个问题上面说得很清楚了。
    第二个问题,当虚拟机生产对象的时候会申请内存空间(怎么申请的,你去看汇编程序设计以及寄存器寻址方式),然后如果引用是静态成员变量,则引用放在方法区中,如果引用是成员变量则放在堆中,如果引用是局部变量,则成为局部变量索引(局部变量没有变量名称,它只是一个索引项)。
    第三个问题,虚拟机规范没有规定引用应该去怎么实现,如今应用大致有两种实现方式,一种是引用直接就是一个指向堆内存的指针,另外一个是引用指向方法区类对象映射表中的某个项,映射表中的项再以指针的形式指向堆内存空间,具体实现可能还有更多情况,所以这个问题你不必太过于探讨。
      

  4.   

    前几天看了栈堆内存:
    总结了下:有些是根据网上总结的(由于时间的问题,还没结完)
        有错的地方希望提出 毕竟我也是新手 总结不好的地方不要拍砖!
       
    栈内存:
         在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 栈内存主要存放的是基本类型类型的数据 如、( 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()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
      

  5.   

    深入java虚拟机 这本书写的很详细,你看了就完全清楚了。不过可能这个书买不到了,好像没有继续印刷了。
      

  6.   

    大概使这个样子的
    在函数中定义的基本类型的变量和对象的引用变量都在函数的栈内存中分配、
    堆内存用来存放由 new 、 newarray 、 anewarray 和 multianewarray 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。找找尚学堂、马士兵、张孝祥的视频看看就懂了
      

  7.   

    栈空间stack用来存放局部变量
    堆空间heap存放new出来的东西
    通俗,呵呵
      

  8.   

    堆内存 存储new出来的对象和数组元素栈内存 存储变量和对象的引用变量
      

  9.   

    哎,大家天天说学Java的必看《Thinking in java》
       可怎么就没人看呢?
      楼主去看《Thinking in java》的第二章 “一切都是对象”具体多少页不清楚了
         肯定很详细,我曾经看过
           在不懂,你拿到砍我。(在砍我的时候要想想砍是犯法的。。嘿嘿..)
      

  10.   

    Java的数据类型只有原始类型和引用类型两种。对于原始类型如int、long、boolean等,局部变量保存的是其值,也因此这个值存在于栈上;对于引用类型,局部变量保存的是其引用,也因此这个引用存在于栈上,而被引用的实例是(绝大多数,因为字符串直接量例外)存在于堆上的。因此说局部变量存在于栈上,是准确的。
      

  11.   

    栈内存:       在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。 栈内存主要存放的是基本类型类型的数据 如、( 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  貌似不太对,看看这个public static void main(java.lang.String[] args);
        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()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。    
      

  12.   


    6楼的说法基本上是对的,而且深有同感,部分中国人的书都是你抄我的,我抄你的,结果误导了一大批人,但也不是不要看中国人写得书,我觉得侯捷写的书就很好,最后推荐楼主看看《Java虚拟机规范》和《深入Java虚拟机》
      

  13.   

    学习了!
    web 网站建设
      

  14.   

    栈(stack):局部变量,引用变量
    堆(heap):Class ,Array
      

  15.   

    1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,详见第3点。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
      

  16.   

    什么是堆  ?  
      当对象你把他NEW出来的时候 JVM就内存当中开辟了一块空间 这块空间就叫做堆 ,所有NEW出来的东西都放在堆里面 
    什么是栈 ?
      除了NEW出来的东西 其他的放到栈里面  
      

  17.   

    建议看看<<Thinking in java>>书中“存储到什么地方”那块知识。
    推荐资源下载:http://download.csdn.net/detail/qmx_zhq/3410905
      

  18.   

    Java 把内存划分成两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
      堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
      这也是 Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!
      

  19.   

    1、一看new 关键字就分配内存和实例化
    1、栈是分配内存地址,而堆空间是分配内存,有栈指向堆空间里面的对象