A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 严明 初级黑马   /  2012-6-26 18:36  /  3290 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

byte[] buffer = newbyte[1024];

此时的字节数组是在 堆内存中吗? 还是在 栈内存中?  

什么时侯会用到堆内存? 什么时侯用到栈内存? 一个数据进入了堆内存就不能转移到栈内存了吗?

12 个回复

倒序浏览
本帖最后由 韦念欣 于 2012-6-26 18:43 编辑

byte[] buffer = new byte[1024];

buffer类似于一个引用,这个引用在栈内存,它的值是一个地址,这个地址指向堆内存中的new byte[1024]这块空间。

java将内存分成四个区域:
栈内存:存储的是对象的名称,实际上时对象对堆内存的引用地址;当然还存储一些局部基本数据类型变量,如int,double
堆内存:只要继承于Object的类生成的对象,都存到堆内存中。(除了它的名称,即地址引用保存在栈内存)
全局代码区:保存所有的方法
全局数据区:保存所有的static属性
回复 使用道具 举报
buffer是一个引用,这个引用在栈内存,它的值是一个地址,它的地址指向堆内存中的byte[1024]这块空间
Java 把内存划分成两种:
    一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

    堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走
回复 使用道具 举报
任何程序在内存中运行,内存都要给它分配空间,JAVA在内存中分布的两个内存空间为:栈与堆。
栈:是用来存放局部定义的内容(变量),且栈内存中的内容只要不被使用,就会立即释放(最明显的就是for循环)
堆:是用来存放实体(数组和对象都在堆内存当中)。
回复 使用道具 举报
new 就是新建了一个数组,数组的内容是在堆内存中,而在存放堆内存中就有一个地址,在栈内存中存放的就是这个地址

回复 使用道具 举报
本帖最后由 吴林军 于 2012-6-27 16:05 编辑

此时的字节数组是存放在堆内存里的!
Java 把内存划分成两种:
一种是栈内存,另一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都是放在栈内存的;
堆内存用来存放由 new 创建的对象和数组.
栈有一个很重要的特殊性,就是存在栈中的数据可以共享。
回复 使用道具 举报

byte[] 是一个数组,不是基本数据类型,而是引用类型,所谓引用类型,即buffer变量存放的是数据的地址而不是变量的指,简单的说凡是new出来了的都是分配在堆上的。
回复 使用道具 举报
buffer 是一个引用变量,是对堆里面数据的一个引用, buffer是存放在栈里面的,而里面的数据时存放在堆里的,java数据类型中除了基本数据类型,外 其他都是引用对象,数组也是一种引用对象,只要用new关键字new出来的 ,都会在内存当中分配出一块空间,然后将该空间的引用返回给你定义的引用变量,引用变量和基本类型数据应该是放在栈里面的,然后指向堆里面的数据
回复 使用道具 举报
byte[] buffer = new byte[1024];
byte[] buffer这是声明数组,也是引用,此时buffer会在栈中开辟一个空间存在栈区,new创建的数组元素存在于堆内存中,并且对应一个地址值,此时buffer这个引用指向了这个地址值。
数据在堆内存中有可能后来又在栈内存中,这个要看具体情况,比如有个成员对象,Userinfo ,然后在某个方法内又定义了一个局部属性Userinfo的实例。
如果用属性值拷贝的方式赋值,比如copyProperites这个方法。那么堆栈数据是会相互串门的,分配的空间不变,只是值的交换。
下面是栈内存和堆内存的具体区别:
Java程序在运行时,需要在内存中分配空间。为了提高运算效率,又对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
栈内存(栈区):用于存储局部变量,当数据使用完,所占空间会自动释放。
堆内存(堆区):
数组和对象,通过new建立的实例都存放在堆内存中。
每一个实体都有内存地址值(本节即指数组地址)。
实体中的变量在没有赋值的情况下都有默认初始化值。默认值是根据数组中元素的类型而定,若是int型数组 ,默认值是0。若是double型数组,默认值是0.0,若是float型数组,默认值是0.0f,若是boolean型数组,默认值是false,若是char型数组,默认值是\u0000即是一个空位,相当于空格,若是String类型,默认值是null。如果想给堆内存中的一个实体0角标赋值,格式为x[0]=10;
实体不再被使用,会在不确定的时间内被垃圾回收器回收(java虚拟机的回收机制)。
回复 使用道具 举报
余清兰 发表于 2012-6-27 10:20
byte[] buffer = new byte[1024];
byte[] buffer这是声明数组,也是引用,此时buffer会在栈中开辟一个空间 ...

解释的很细,还拓展了很多,强烈推荐版主给分奖励!
回复 使用道具 举报
buffer是一个引用,这个引用在栈内存,它的值是一个地址,它的地址指向堆内存中的byte[1024]这块空间
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。

堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。

引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!


回复 使用道具 举报
创建的数组存放在堆里,而创建的buffer则在栈里,是一个引用(类似于C中的指针),存放的是堆内存的首地址
回复 使用道具 举报
乞文超 发表于 2012-6-27 16:07
buffer是一个引用,这个引用在栈内存,它的值是一个地址,它的地址指向堆内存中的byte[1024]这块空间
Java ...

谢谢你的解释, 很清楚 ,但我还有点小疑问, 有点钻牛角尖的 ,请见谅!



public class StaticDemo
{
        static int a = 1;                                // a 存放在方法区中,方法区是属于堆内存还是在栈内存中? 是在编译过程中放进去的?还是编译之后放进方法区的?


        static String str = "helloworld";          /* "helloworld "是从常量池中取给str的,如果常量池中没有"helloworld "这个字符串,
                                                                    是不是就会new 一个字符串给str ? 相当于 static String str = (new String("hellowird"));就会产生对象了? */         
               
        static String str_copy = (new String("hellowird"));         // 既然会 new 一个对象给str_copy ,怎么保证 其他类直接调用 (StaticDemo.str_copy)  时不会涉及到对象的创建?
         
       

        int a2 = 1;                                                // a2 是在new 对象的时侯与对象一起放入堆内存的.这我知道.
        String str2 = "hello world";                       /* 如果常量池中没有"helloworld" ,是先new 一个字符串"hello world" 让 str2 来引用,
                                                                      然后再 new StaticDemo() 的时侯将这个 str2引用变量 随对象一起 放到堆内存中吗?  可是Java中的引用变量不是要 放在栈内存中的吗?    */
       
       
       

        public static void say()                         //这个方法在 new StaticDemo() 之前是放在 栈内存 还是堆内存?
        {

                System.out.println(a  + str );
        }

       
       
                public void say2()                            //这个方法在new StaticDemo()之后肯定是放在 堆内存 生成的对象里面. 这我知道.
        {

                System.out.println(a + a2 + str + str2);
        }
       
       
        public static void main(String[] args)
        {
               
        }

}


回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马