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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黑马王冬冬 中级黑马   /  2012-7-11 00:49  /  3496 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 muyexi 于 2012-7-11 15:20 编辑

在看毕老师java视频的过程中,发现老师经常画图来演示变量啦,对象啦的什么在栈与堆中的分配,可我一直不明白栈与堆到底是什么,又有那些区别和联系,平常看书也没有发现讲解相关知识的资料,哪位高手指点一下,或者给出一些相关书籍的线索?实在很好奇啊!

11 个回复

倒序浏览
毕老师讲的内存一课就介绍了了JVM内存分Heap(堆)和Stack(栈)两类内存空间。栈空间是用于线程的方法调用的
从堆和栈的功能和作用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的.而这种不同又主要是由于堆和栈的特点决定的:

堆区: Heap
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息的引用。(class的目的是得到操作指令) 。
2.jvm的堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身 。
栈区: Stack
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中 。
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
一个简单的例子
public   class AppMain                //运行时, jvm 把appmain的信息都放入方法区
{
public   static   void main(String[] args) //main 方法本身放入方法区。
{
Sample test1 = new Sample( " 测试1 " );   //test1是引用,所以放到栈区里, Sample是自定义对象应该放到堆里面
Sample test2 = new Sample( " 测试2 " );

test1.printName();
test2.printName();
}
} Sample.java

public   class Sample        //运行时, jvm 把appmain的信息都放入方法区
{
/** 范例名称 */
private name;      //new Sample实例后, name 引用放入栈区里, name 对象放入堆里

/** 构造方法 */
public Sample(String name)
{
this .name = name;
}

/** 输出 */
public   void printName()   //printName方法本身放入 方法区里。
{
System.out.println(name);
}
}

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

回复 使用道具 举报
java中内存分为四种存储空间:
从下往上我简单解释;
代码区:存放代码。
静态数据区:存放static(全局的)的数据。
栈:我个人理解为它是存放对象名字的,就像c语言指针一样,它具有一个指向,指向堆内存。
堆:存放属性的。
回复 使用道具 举报
本帖最后由 张天天 于 2012-7-11 06:11 编辑

堆、栈都是内存的一块分区,在java中说的堆、栈应该指的是JVM中的
Java栈,它主要用来存储线程执行过程中的局部变量,方法的返回值,以及方法调用上下文。栈空间随着线程的终止而释放
Java中堆是由所有的线程共享的一块内存区域,堆用来保存各种JAVA对象,比如数组,线程对象等。
堆很灵活,但是不安全。对于对象,我们可以
栈不灵活,但是很严格,是安全的,易于管理。因为只要上面的引用没有销毁,下面引用就一定还在动态地创建、销毁,
可以参考图,如下:
回复 使用道具 举报
首先要知道内存的结构是什么样的?
内存分为4个部分,栈内存,堆内存,codesegment,datesegment。
1 栈内存的作用和特点时什么?
栈内存存储局部变量,当数据使用完,所占空间会自动释放。
2 堆内存作用是什么?特点是什么?
通过new关键字建立的实体都存放在堆内存中,实体包括数组和对象。
特点:每一个实体都有内存地址值。
实体中的变量都有默认初始化值。
实体不再被使用,会在不确定的时间内被垃圾回收器回收。

C:\Users\Administrator\Desktop\1.png

1.png (221.34 KB, 下载次数: 28)

1.png
回复 使用道具 举报
栈内存:存储的都是局部变量。变量运算区域一结束,就释放。
                                局部变量:在方法上的参数,方法内的变量,语句中的变量。
堆内存:存储的是数组和对象,简单说,堆内存中存储都是实体。
                        实体就是可以存储多个数据地方。记住,只要是用new建立都存储在堆内存中。
                        特点:1,任何实体都有内存地址值。
                              2,堆内存中的变量都有默认初始化值。
                              3,垃圾回收机制。
栈内存: 用于存储局部变量,当数据使用完,所占空间会自动释放。
堆内存:数组和对象,通过new建立的实例都存放在堆内存中。
特点:1,每一个实体都有内存地址值。
     2,实体中的变量都有默认初始化值
       3,实体不再被使用时,会在不确定的时间内被垃圾回收器回收
注意:记住,只要用new建立的都存储在堆内存中。

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

回复 使用道具 举报
首先 你要搞清楚 堆和栈 是虚拟出来的概念 他们在内存中都只是一块区域,只是他们的存取规则被人为的限制了,一般来说  把类似指针的地址数据放在同一块内存区域这块区域遵守栈的存取规则我们就称之为栈 然后把主要的数据放在同一块内存区域并遵守堆的存取规则 我们称之为堆 其实他们物理上都是一样的东西 只是我们附加上了一些概念 最后之所以这么做 是为了优化存取速度 。
回复 使用道具 举报
不要那么复杂的说,在此,我简单说一下:
java堆与栈 java String分配内存空间

栈内存:
1、基础类型,对象引用(堆内存地址)
2、存取速度快
3、数据大小声明周期必须确定
4、创建之后值可以改变
5、共享特性
6、栈中如果有字符串,则直接引用,如果没有,开辟新的空间存入值
7、创建之后值可以改变


堆内存:
1、由new创建的对象和数组,
2、相对于栈内存较慢
3、分配的内存由java虚拟机自动垃圾回
4、收器管理。动态分配内存大小
5、String类声明后则不可改变  
6、每new一次在堆内存中生成一个新的对象。
7、String类声明后则不可改变   
回复 使用道具 举报
一、程序在编译的时候占用的内存分为以下几个部分:

1 、栈区( stack )— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限.

2 、堆区( heap )— 亦称动态内存分配.程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存.但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表.

3 、全局区(静态区)( static )— 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由有系统释放.

4 、常量区 — 常量字符串就是放在这里的.程序结束后由系统释放.

5 、程序代码区 — 存放函数体的二进制代码.
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。


希望对你有帮助

评分

参与人数 1技术分 +1 收起 理由
黑马张扬 + 1

查看全部评分

回复 使用道具 举报
我觉得没那么麻烦,堆和栈不需要那么深的理解
只是要明白是干什么的,能便于你理解代码就行了
1.进出顺序不同,堆是先进先出,而栈是先进后处

2. 栈的优势是,存取速度比堆要快,但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享,
堆的优势是,可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢,

3. 栈(stack)与堆(heap)都是Java用来在内存中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。

这是堆和栈的区别,其实你只需要知道,栈通过堆中数据储存的内存地址来指向堆的内存就可以了,看一下毕老师画的图,理解一下是怎么指向的就可以了
回复 使用道具 举报
栈是临时的,不用时自己释放,堆却不会自己释放,我觉得知道这个就够用了
回复 使用道具 举报
堆内存就是你用new 修饰符创建的内容会在堆内存中开辟一段空间,存放new出来的对象,比如 new String("ABC"), 就在堆内存空间分配了一块空间,它的内容是"ABC",而栈内存是你存放引用变量的地方,比如String a = new String("ABC")中 a这个变量就是在栈内存空间中分配了一块空间,它指向堆内存中内容为"ABC"的地址。

栈内存:主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。
堆内存:用于存储对象。

堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马