堆和栈 内存分配 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是如何进行内存管理的,是如何垃圾回收的......这样,我们才能写出 ...
随机推荐
- PHPCMS get当中使用limit
最近在用PHPCMS V9做一个站子,发现get标签非常好用,自定义模型后get几乎变成万能的了.但是PHPCMS升级到V9后,把2008的很多功能都去掉了,比如get标签中,在后面自动添加了一个LI ...
- LINUX单网卡绑定多个IP
在linux下,我们有时候需要给单网卡设置不同的IP地址,这样就涉及到单网卡绑定多个IP地址的情况.使用本方法可以方便的为单网卡绑定多个IP地址.笔者使用的环境是centos5.6,应该在fedora ...
- tomcat源码阅读
1 工具准备 需要SVN.Maven.JDK.Eclipse.Eclipse M2插件 2 下载源码及发布包 源码在这里:http://svn.apache.org/repos/a ...
- Ncurses <一>
前言: 最好的ncurses教程是 ncurses HOWTO,网上有中文版 编译ncurses引用的程序,需要加编译参数 -lncurses 并在.c文件中包含 ncurses.h头文件 1. 启动 ...
- [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】
题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...
- SharePoint DataFormWebPart 通过Caml和xslt聚合内容
以下是一个例子,SPDataSource用于查询内容,DatasourceMode属性指定查询范围(网站集,网站,列表),SelectCommand是Caml查询:Xsl展示内容,下面列子是用tabl ...
- Dollars
uva147: 题意:给你几种钱币,在给你一个钱的数目,问有多少种用这些钱来组成这个数目. 题解:完全背包,不过此时要把钱的数目*100,因为是小数,背包的容量都是整数,然后dp,求出每个容量的数目即 ...
- Top WAF
http://blog.csdn.net/force_eagle/article/details/9396087
- KeilC51使用详解 (一)
第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性.可维护性上有明显的优势,因而易学易用.用过 ...
- 看奢侈品Prada如何使用物联网
这是峰哥在一家国际顶级商学院听课的笔记.这是个巨变的时代,有趣的时代. 一 PRADA在纽约的旗舰店.每件衣服上都有RFID码.每当一个顾客拿起一件PRADA进试衣间,RFID会被自动识别,试衣间里的 ...