堆和栈 内存分配 heap stack
Java中的堆和栈
在【函数】中定义的一些【基本类型的变量】和【对象的引用变量】都是在函数的【栈内存】中分配的。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会【自动】释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。【堆内存】用于存放由new创建的【对象和数组】。在堆中分配的内存,由【java虚拟机】自动垃圾回收器来管理。在【堆】中产生了一个数组或者对象后,还可以在【栈】中定义一个【特殊的变量】,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的【引用变量】,以后就可以在程序中使用栈内存中的引用变量,来访问堆中的数组或者对象。引用变量相当于为数组或者对象起的一个【别名】,或者代号。【引用变量是普通变量】,定义时在栈中分配内存,【引用变量在程序运行到作用域外释放】。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在的代码块之外,数组和对象【本身】占用的堆内存也不会被释放(注意,此时仅仅是引用变量被释放了),数组和对象在没有引用变量指向它的时候,才变成【垃圾】(垃圾就是指未回收的、之后不会再使用的对象)。虽然垃圾不会再被使用,但是仍然占着内存,在随后的一个【不确定】的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因!栈与堆都是Java用来在内存中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。Java的堆是一个运行时数据区,类的对象从中分配空间。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量和对象句柄。栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:int a = 3;int b = 3;编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4这个值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的【共享】与两个对象的【引用】同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个引用变量修改了这个对象的内部状态,会影响到另一个引用变量。按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的。静态存储分配是指在【编译时】就能确定每个数据目标在【运行时】刻的存储空间需求,因而在编译时就可以给他们分配【固定的】内存空间。这种分配策略要求程序代码中不允许有【可变数据结构】(比如可变数组)的存在,也不允许有【嵌套或者递归的结构】出现,因为它们都会导致编译程序无法计算准确的存储空间需求。栈式存储分配也可称为【动态】存储分配,是由一个类似于堆栈的运行栈来实现的。和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未知的,只有到运行的时候才能够知道,但是规定在运行中【进入一个程序模块时】,必须知道该程序模块所需的数据区大小,才能够为其分配内存。和我们在数据结构所熟知的栈一样,栈式存储分配按照先进后出的原则进行分配。静态存储分配要求【在编译时】能知道所有变量的存储要求,栈式存储分配要求【在过程的入口处】必须知道所有的存储要求,而堆式存储分配则专门负责在编译时或运行时模块入口处【都无法确定】存储要求的数据结构的内存分配,比如可变长度串和对象实例。堆由【大片】的可利用块或空闲块组成,堆中的内存可以按照任意顺序分配和释放。
演示代码
public class Test {public static void main(String[] args) {Person person = new Person("1");//在【堆内存】中初始化一个对象,然后在【栈内存】中创建一个变量person,并让person指向此堆内存中的对象Person newPerson = person;//在【栈内存】中创建一个新的变量newPerson,赋值的含义为:让newPerson指向person所指向的堆内存中的同一个对象newPerson.name = "2";System.out.println(person.name + "-" + newPerson.name);//2-2newPerson = new Person("3");//在【堆内存】中初始化一个对象,然后让newPerson指向此对象,此时person所指向的对象还是之前的那个对象System.out.println(person.name + "-" + newPerson.name);//2-3}public static class Person {String name;public Person(String name) {this。name = name;}}}
堆和栈 内存分配 heap stack的更多相关文章
- 【转载】c++中堆、栈内存分配
一.内存划分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数参数值,局部变量值等.其操作方式类似于数据结构中栈.2.堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时 ...
- c++中堆、栈内存分配
转自:https://blog.csdn.net/qingtingchen1987/article/details/7698415 一个由C/C++编译程序占用内存分为以下几个部分1.栈区(stack ...
- Java中堆内存与栈内存分配浅析
Java把内存划分成两种:一种是栈内存,另一种是堆内存.在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间, ...
- 如何让对象只在堆或者栈中分配空间ANDC++禁止一个类被继承
在开始之前先来分析一下C++中的new运算符和operator new之间的关联. new:指我们在C++里通常用到的运算符,比如A* a = new A或者调用带参数的构造函数; 对于new来说, ...
- jvm 虚拟机参数_栈内存分配
1.参数 -Xss 指定线程最大的栈空间,整个参数也直接决定了函数可调用的最大深度 2.测试代码 private static int count; public static void addCou ...
- 从一个微型例子看“C/C++的内存分配机制”和“数组变量名与指针变量名”(转)
C++的内存有五大分区:堆区.栈区.自由存储区.全局/静态存储区.常量存储区. 五个数据段:数据段.代码段.BSS段.堆.栈 内存分配方式有三种: 从静态存储区域分配.内存在程序编译的时候就已经分配好 ...
- 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型
小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...
- Java中堆内存(heap)和栈内存(stack)的区别
在Java代码中,常常会使用到这样的类的声明实例化: Person per = new Person(); //这其实是包含了两个步骤,声明和实例化 Person per = null; //声明一个 ...
- .NET的堆和栈01,基本概念、值类型内存分配
当我们对.NET Framework的一些基本面了解之后,实际上,还是很有必要了解一些更底层的知识.比如.NET Framework是如何进行内存管理的,是如何垃圾回收的......这样,我们才能写出 ...
随机推荐
- Sass学习
1.1下载地址: http://rubyinstaller.org/downloads 2.1 安装 SASS是Ruby语言写的,但是两者的语法没有关系.不懂Ruby,照样使用.只是必须先安装Ruby ...
- iscc2016-好长的字符串
Vm0wd2QyVkhVWGhVYmxKV1YwZDRXRmxVUm5kVlJscHpXa2M1VjFKdGVGWlZNbmhQWVd4YWMxZHViRmROYWxaeVdWZDRZV014WkhG ...
- nginx+uwsgi+django
上一涨讲解了如何使用nginx+uwsgi部署wsgi application 其实django配置方式和 application都一样,因为如果我们对application进行扩展就是一个WSGI ...
- 最新选择Godaddy主机方案美国数据中心教程指导
随着Godaddy官方管理层的变动之后,主营重心已经从当初的域名开始转向到域名和主机产品上.这点我们从其发布域名优惠信息的频率也可以看到,而且我们可以看到常年的主机半价优惠,以及针对主机销售年付方案赠 ...
- 通过GetManifestResourceStream加载文件出现错误提示“null值”对于“stream”无效[转]
本文解决了我的问题,收藏一下. 原文地址:http://blog.sina.com.cn/s/blog_a67799f601010atz.html 在做Mobile开发时,需要引入图片,用到了这个方法 ...
- Xcode 5 解决 The operation couldn’t be completed. (NSURLErrorDomain error -1012.) 问题
使用Xcode6.1 SVN 出现问题 The operation couldn’t be completed. (NSURLErrorDomain error -1012.) 解决方法: 打开终端 ...
- Unity3d 项目管理 版本管理
Unity3d中项目管理 版本管理 如果在提交文件的时候发现提示有"先更新,再提交的"提示的时候,这是因为,A提交了一个版本文件,版本是13,那么你还在修改版本为12的文件 ...
- 【面试&笔试】ASP.NET的相关问题
1. 介绍ASP.NET 答:ASP.NET不是一种语言,而是创建动态web页的一种强大的服务器端技术,它是Microsoft.NETFramework中一套用于生成Web应用程序和Web服 ...
- aix ipcs使用说明
ipcs: -q Writes information about active message queues -o Writes the following usage ...
- Expanding Rods(二分)
Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10287 Accepted: 2615 Description When ...