java虚拟机栈深度中堆和栈的区别

JVM中堆和栈(转载/整理) - 夜月升 - 博客园
JVM的内存有很重要的两部分就是堆heap和栈stack(这句是废话)。
& & & Stack(栈)是JVM的内存指令区。Stack管理很简单,push一定长度字节的数据或者指令,Stack指针压栈相应的字节位移;pop一定字节长度数据或者指令,Stack指针出栈。Stack的速度快,管理简单,并且每次操作的数据或者指令字节长度和生存期是已知的。所以Java 基本数据类型,Java 指令代码,常量都保存在Stack中。  Heap(堆)是JVM的内存数据区。Heap 的管理复杂,每次分配不定长的内存空间,专门用来保存对象的实例。在Heap 中分配一定的内存来保存对象实例,实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中),在Heap 中分配一定的内存保存对象实例和对象的序列化比较类似。而对象实例在Heap 中分配好以后,需要在Stack中保存一个4字节的Heap 内存地址,用来定位该对象实例在Heap 中的位置,便于找到该对象实例。
& & &由于Stack的内存管理是顺序分配的,而且定长,不存在内存回收问题;而Heap 则是随机分配内存,不定长度,存在内存分配和回收的问题;因此在JVM中另有一个GC进程,定期扫描Heap ,它根据Stack中保存的4字节对象地址扫描Heap ,定位Heap 中这些对象,进行一些优化(例如合并空闲内存块什么的),并且假设Heap 中没有扫描到的区域都是空闲的,统统refresh(实际上是把Stack中丢失了对象地址的无用对象清除了),这就是垃圾收集的过程。
& & &换一种说法说明JVM堆和栈的区别就是:JVM栈是运行时的单位,而JVM堆是存储的单位。& & &JVM栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;JVM堆解决的是数据存储的问题,即数据怎么放、放在哪儿。& & &在Java中一个线程就会相应有一个线程JVM栈与之对应,这点很容易理解,因为不同的线程执行逻辑有所不同,因此需要一个独立的线程JVM栈。而JVM堆则是所有线程共享的。JVM栈因为是运行单位,因此里面存储的信息都是跟当前线程(或程序)相关信息的。包括局部变量、程序运行状态、方法返回值等等;而JVM堆只负责存储对象信息。& & &在Java中,Main函数就是JVM栈的起始点,也是程序的起始点。
程序要运行总是有一个起点的。同C语言一样,java中的Main就是那个起点。无论什么java程序,找到main就找到了程序执行的入口
堆栈上分别保存的数据及非静态方法与静态方法的区别
我们首先要搞清楚的是什么是数据以及什么是指令。然后要搞清楚对象的方法和对象的属性分别保存在哪里。
& & &1)方法本身是指令的操作码部分,保存在Stack中;
& & &2)方法内部变量作为指令的操作数部分,跟在指令的操作码之后,保存在Stack中(实际上是简单类型保存在Stack中,对象类型在Stack中保存地址,在Heap 中保存值);上述的指令操作码和指令操作数构成了完整的Java 指令。
& & &3)对象实例包括其属性值作为数据,保存在数据区Heap 中。
  非静态的对象属性作为对象实例的一部分保存在Heap 中,而对象实例必须通过Stack中保存的地址指针才能访问到。因此能否访问到对象实例以及它的非静态属性值完全取决于能否获得对象实例在Stack中的地址指针。
  非静态方法和静态方法的区别:
  非静态方法有一个和静态方法很重大的不同:非静态方法有一个隐含的传入参数,该参数是JVM给它的,和我们怎么写代码无关,这个隐含的参数就是对象实例在Stack中的地址指针。因此非静态方法(在Stack中的指令代码)总是可以找到自己的专用数据(在Heap 中的对象属性值)。当然非静态方法也必须获得该隐含参数,因此非静态方法在调用前,必须先new一个对象实例,获得Stack中的地址指针,否则JVM将无法将隐含参数传给非静态方法。
  静态方法无此隐含参数,因此也不需要new对象,只要class文件被ClassLoader load进入JVM的Stack,该静态方法即可被调用。当然此时静态方法是存取不到Heap 中的对象属性的。
  总结一下该过程:当一个class文件被ClassLoader load进入JVM后,方法指令保存在Stack中,此时Heap 区没有数据。然后程序技术器开始执行指令,如果是静态方法,直接依次执行指令代码,当然此时指令代码是不能访问Heap 数据区的;如果是非静态方法,由于隐含参数没有值,会报错。因此在非静态方法执行前,要先new对象,在Heap 中分配数据,并把Stack中的地址指针交给非静态方法,这样程序计数器依次执行指令,而指令代码此时能够访问到Heap 数据区了。
Java中的栈、帧和线程& & & JVM是基于栈的虚拟机.JVM为每个新创建的线程都分配一个栈.也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。JVM对栈只进行两种操作:以帧为单位的进栈和出栈操作。& & & 那么这帧又是什么呢?& & & 栈帧由三部分组成:局部变量区、操作数栈、帧数据区。局部变量区和操作数栈的大小要视对应的方法而定,他们是按字长计算的。但调用一个方法时,它从类型信息中得到此方法局部变量区和操作数栈大小,并据此分配栈内存,然后压入Java栈。& & & 局部变量区,局部变量区被组织为以一个字长为单位、从0开始计数的数组,类型为short、byte和char的值在存入数组前要被转换成int值,而long和double在数组中占据连续的两项,在访问局部变量中的long或double时,只需取出连续两项的第一项的索引值即可,如某个long值在局部变量区中占据的索引时3、4项,取值时,指令只需取索引为3的long值即可。& & & 操作数栈和局部变量区一样,操作数栈也被组织成一个以字长为单位的数组。但和前者不同的是,它不是通过索引来访问的,而是通过入栈和出栈来访问的。可把操作数栈理解为存储计算时,临时数据的存储区域。& & & 除了局部变量区和操作数栈外,Java栈帧还需要一些数据来支持常量池解析、正常方法返回以及异常派发机制。这些数据都保存在Java栈帧的帧数据区中。1)当JVM执行到需要常量池数据的指令时,它都会通过帧数据区中指向常量池的指针来访问它。2)除了处理常量池解析外,帧里的数据还要处理Java方法的正常结束和异常终止。如果是通过return正常结束,则当前栈帧从Java栈中弹出,恢复发起调用的方法的栈。如果方法又返回值,JVM会把返回值压入到发起调用方法的操作数栈。3)为了处理Java方法中的异常情况,帧数据区还必须保存一个对此方法异常引用表的引用。当异常抛出时,JVM给catch块中的代码。如果没发现,方法立即终止,然后JVM用帧区数据的信息恢复发起调用的方法的帧。然后再在发起调用方法的上下文重新抛出同样的异常。
& & & 帧在方法调用时被创建,在方法结束时销毁。
& & &Java栈是与每一个线程关联的,JVM在创建每一个线程的时候,会分配一定的栈空间给线程。栈空间随着线程的终止而释放。常见的StackOverflowError是因为在线程执行的过程中,栈空间不够用,JVM就会抛出此异常,这种情况一般是死递归造成的。& & &线程正在执行的方法称为当前方法,当前方法所使用的帧称为当前帧。一个线程创建的帧局部于该线程,其它线程不能引用。
& & &静态存储要求在编译时知道所有变量的存储要求;栈式存储要求在过程(程序或方法)的入口处知道所有变量的存储要求;堆式存储则专门负责编译时或运行时无法确定存储要求的数据结构的内存分配。JVM堆和栈的区别
对象还是放在堆。
程序的可见度 堆对于整个应用程序都是共享、可见的。 栈只对于线程是可见的。所以也是线程私有。他的生命周期和线程相同。 参考资源
Java中堆和栈的区别详解 Java中堆内存和栈内存详解 JAVA中堆和栈的区别 什么是堆和栈,它们在哪儿?
16:37&&&[]
;&hello&csdn&;&//存放在静态区!
栈和堆都是在进程地址空间中分配,还是堆是在操作系统的空闲空间中分配然后在进程的全局变量区引用这些空间?
char&arr[10]&=&{0};&//&可以
17:26&&&[]
一、定义& 1、堆:FIFO队列优先,先进先出。堆存放在二级缓存中,调用对象的速度相对慢一些,生命周期由虚拟机的垃圾回收机制决定。 2、栈:FILO先进后出,暂存数据的地方。栈存放在一级缓存中,存取速度较快,“栈是限定仅在表头进行插入和删除操作的线性表”。
二、存储的数据类型 1、堆
20:27&&&[]
一、在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。
当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
堆内存用来存放由new创建的对象和数组。
17:24&&&[]
管理方式: 对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。申请大小:栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的
15:14&&&[]
堆和栈的区别&
栈与堆都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。&
Java的堆是一个运行时数据区,类的(对象从中分配空间。这些对象通过new、newarray、anewarray和
-17:32&&&[]
。这种情况下,不免让很多人更加费解前面的问题。事实上,堆和栈都是内存中的一部分,有着不同的作用,而且一个程序需要在这片区域上分配内存。众所周知,所有的Java程序都运行在JVM虚拟机内部,我们这里介绍的自然是JVM(虚拟)内存中的堆和栈。 区别 java中堆和栈的区别自然是面试中的常见问题,下面几点就是
09:10&&&[]
书,书架这种机制不同于箱子,我们可以直接取出我们想要的书。 内存分配中的栈和堆 &&& 然而我要说的重点并不在这,我要说的堆和栈并不是数据结构的堆和栈,之所以要说数据结构的堆和栈是为了和后面我要说的堆区和栈区区别开来,请大家一定要注意。 &&nbsp
13:32&&&[]
;in&=&null,栈中存储速度快
堆:主要放new出来的对象,实例变量,如数组、new出来的对象,堆是动态分配内存空间的,所以带速度慢点。
说简单点,就是堆适用于存储对象实例,和类信息的,其中的数据可以为多线程共享,里面的数据存在时间视对象与类的存在时间而定。一般较长,而且
-16:22&&&[]
java的栈和堆是在JVM里,还是在电脑的内存里?
回复讨论(解决方案)
等待砖家解答
在电脑内存上啊。其实java编译后生成&byte&code,然后JVM就执行byte&code&调用本地资源。
JVM。。。是虚拟机。。。
-19:45&&&[]
平常用的globalallcol,函数是不是在堆或者栈上分配内存呢,VIRTUALALLOC是在哪分配内存呢
回复讨论(解决方案)
GlobalAlloc
&&Allocates&the&specified&number&nbsp
-09:32&&&[]
一直对这两个概念比较模糊,心里不安,所以下决心好好的看了一下它。 它们都是计算机中的数据结构。 堆(heap):把堆比作一个大仓库,仓库里面可以放很多东西。当我们创建一个对象时(new XXX),首先会在堆里面开辟一块空间放置对象本身,然后再把对象的引用地址放入栈中。最后访问该对象时,先通过栈找到
12:44&&&[]

我要回帖

更多关于 java虚拟机堆栈 的文章

 

随机推荐