大家好,又见面了,我是你们的朋友全栈君。...一、什么是栈 栈(stack)是一种先进后出的有序列表,其中的元素只能在线性表的同一端进出, 允许元素插入和删除的一端被称为栈顶(top),固定的另一端被称为栈底(button)。...二、数组简单实现栈 由于栈是只在一端进出,也就是说相比队列实际上只需要有一个栈顶指针top即可: 当栈空时top为-1 入栈后top+1 出栈后top-1 根据思路我们可以用数组实现一个简单的栈: /*...假设现有头结点,一号元素A,我们需要往里面插入或弹出B,,由于要实现“先进后出”的效果: 入栈时,B需要插入头结点和A之间,取代A的位置: B.next = head.next,也就是B指向A head.next...:huang * @Date:2020-06-20 10:19 * @Description:节点类 */ public class Node { //数据 Object data
,堆的内存可以是固定的,也可以动态增长,并且不要求在内存里面是必须连续的,如果计算需要更多的内存,超过了当前有效的内存,那么就会抛出OutOfMemoryError异常。...此外还负责方法的调用和返回,java的栈仅仅负责 压栈和出栈,栈内存本身是可以从堆上分配出来的,并且栈内存可以是不连续的。...前面说过栈可以存储数据,这其实是在栈帧(frame)里面完成的,主要存储local变量,也执行动态链接,给方法返回值,还负责分发异常。...栈帧与方法与一对一的关系,也就是说,每次虚拟机调用一个方法时,就会生成一个frame,无论是否发生异常,当方法调用完成后总是销毁,正在执行的方法,其frame称为当前栈帧,当前栈帧执行完成会后,就会抛弃...栈里面包含了很多帧,在程序运行时的每个方法,都会生成一个帧入栈,执行的过程就是出栈的过程。如果栈里面引用了成员变量或者其他共享的变量,这个时候需要注意线程安全问题,因为这些变量是存储在堆上的。
每个线程在创建时都会创建一个虚拟机栈,所以虚拟机栈是线程私有的,当线程结束时虚拟机栈也就结束了。JVM对虚拟机栈的操作只有进栈和出栈,所以它的访问速度仅次于程序计数器,也是一种快速有效的分配存储方式。...即只有当前正在执行的方法的栈帧(栈顶栈帧)是有效的,这个栈帧被称为当前栈帧 (Current Frame),与当前栈帧相对应的方法就是当前方法(Current Method),定义这个方法的类就是当前类...4的执行结果给栈帧3,接着,虚拟机会丢弃栈帧4即栈帧4出栈,使得栈帧3重新成为当前栈帧,以此类推,直到方法1执行完成,栈帧1出栈,虚拟机栈被回收。...不管使用哪种方式,都会导致栈帧出栈。不同线程中所包含的栈帧是不允许存在互相引用的,即不可能在一个栈帧之中引用另外一个线程的栈帧。 ” ?...★局部变量表中的数据只有在当前方法中有效。在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程,当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。
栈的运行原理 Jvm直接对Java栈的操作只有两个,就是对栈帧的压栈和出栈,遵循 '先进后出' / '后进先出' 原则 在一跳活动线程中,一个时间点上,只会有一个活动的栈帧,即只有当前正在执行的方法的栈帧...局部变量表中的变量只在当前的方法调用中有效,在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程,当方法调用结束以后,随着方法栈帧的销毁,局部变量也会随之销毁 关于Slot 参数值的存放总是在局部变量数组的...,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)/出栈(pop) 某些字节码指令将值压入操作数栈,其余的字节码指令将操作数取出栈,使用他们后再把结果压入栈。...数据类型 32bit的类型占用一个栈单位深度 64bit的类型占用两个栈单位深度 操作数栈并非采用访问索引的方式来进行数据访问的,而是只能通过标准的入栈(push)/出栈(pop)操作来完成一次数据访问...他甚至可以直接使用本地处理器中的寄存器 直接从本地内存的堆中分配任意数量的内存 并不是所有的JVM都支持本地方法,因为就Java虚拟机规范并没有明确要求本地方法栈的使用语言、具体实现方式、数据结构等
ESP寄存器总是指向堆栈的栈顶,执行PUSH命令向堆栈压入数据时,ESP减4,然后把数据拷贝到ESP指向的地址;执行POP命令时,首先把ESP指向的数据拷贝到内存地址/寄存器中,然后ESP加4。...(第一个参数地址并不一定是EBP+8,后文中将讲到)。...我们知道,参数的地址总是比EBP的值高,而局部变量的地址总是比EBP的值低。而在特定的堆栈帧中,每个参数或局部变量相对于EBP的地址偏移总是固定的。...对的,堆栈帧是被销毁了,但是程序不会自动清理其中的值,因此ReturnValuePointer中的值还是有效的。...如果显式地把类成员函数声明为使用__cdecl或者__stdcall,那么,将采用__cdecl或者__stdcall的规则来压栈和出栈,而this指针将作为函数的第一个参数最后压入堆栈,而不是使用ECX
在 intel x86 的系统中,堆栈在内存中是从高地址向低地址扩展(这和自定义的堆栈从低地址向高地址扩展不同),如下图所示: 因此,栈顶地址是不断减小的,越后入栈的数据,所处的地址也就越低。...ESP 寄存器总是指向堆栈的栈顶,执行 PUSH 命令向堆栈压入数据时,ESP减4,然后把数据拷贝到ESP指向的地址;执行POP 命令时,首先把 ESP 指向的数据拷贝到内存地址/寄存器中,然后 ESP...我们知道,参数的地址总是比 EBP 的值高,而局部变量的地址总是比 EBP 的值低。而在特定的堆栈帧中,每个参数或局部变量相对于 EBP 的地址偏移总是固定的。...对的,堆栈帧是被销毁了,但是程序不会自动清理其中的值,因此 ReturnValuePointer 中的值还是有效的。...如果显式地把类成员函数声明为使用__cdecl或者__stdcall,那么,将采用__cdecl或者__stdcall的规则来压栈和出栈,而this指针将作为函数的第一个参数最后压入堆栈,而不是使用ECX
处理器总是按照PC指向,取指、译码、执行,以此实现了程序转移。 虚拟机栈 虚拟机栈(JVM Stacks),和数据结构上的栈类似,先进后出。...栈帧在虚拟机栈中入栈到出栈(顺序: 先进后出)的过程,其实就对应Java中方法的调用至执行完成的过程 栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素,每个栈帧存储了方法的变量表...图片 其中: 在当前活动线程中,只有位于栈顶的帧才是有效的,称为当前栈帧。正在执行的方法称为当前方法,栈帧是方法运行的基本结构。在执行引擎运行时,所有指令都只能针对当前栈帧进行操作。...方法调用的数据需要通过栈进行传递,每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法调用结束后,都会有一个栈帧被弹出。...直接内存(Direct Memory)并不是Java虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域。
而线程中有千千万万的函数调用,这些函数共享进程的这个栈空间,那么问题就来了,函数运行过程中会有非常多的入栈出栈的过程,当函数返回backtrace的时候怎样能精确定位到返回地址呢?...寄存器是和CPU联系非常紧密的一小块内存,经常用于存储一些正在使用的数据。对于32位架构armv7指令集的ARM处理器有16个寄存器,从r0到r15,每一个都是32位比特。...在这个过程中用到了上面说的寄存器,fp帧指针,它总是指向当前帧的底部;sp栈指针,它总是指向当前帧的顶部。这两个寄存器用来定位当前帧中的所有空间。...lr总是在上一个栈帧(也就是调用当前栈帧的栈帧)的顶部,而栈帧之间是连续存储的,所以lr也就是当前栈帧底部的上一个地址,以此类推就可以推出所有函数的调用顺序。...另外一个比较重要的东西就是出入栈的顺序,在ARM指令系统中是地址递减栈,入栈操作的参数入栈顺序是从右到左依次入栈,而参数的出栈顺序则是从左到右的你操作。
局部变量:相对于成员变量(或属性) 基本数据变量: 相对于引用类型变量(类,数组,接口) 4、 栈的特点 栈是一种快速有效的分配存储方式,访问速度仅次于PC寄存器(程序计数器) JVM直接对java栈的操作只有两个...JVM直接对java栈的操作只有两个,就是对栈帧的压栈和出栈,遵循先进后出/后进先出的和原则。...即只有当前正在执行的方法的栈帧(栈顶栈帧)是有效的,这个栈帧被称为当前栈帧(Current Frame),与当前栈帧对应的方法就是当前方法(Current Method) 执行引擎运行的所有字节码指令只针对当前栈帧进行操作...和出栈pop操作来完成一次数据访问 **如果被调用的方法带有返回值的话,其返回值将会被压入当前栈帧的操作数栈中,**并更新PC寄存器中下一条需要执行的字节码指令。...本质上,方法的退出就是当前栈帧出栈的过程。此时,需要恢复上层方法的局部变量表、操作数栈、将返回值也如调用者栈帧的操作数栈、设置PC寄存器值等,让调用者方法继续执行下去。
请你计算该表达式,返回一个表示表达式值的整数。 注意:两个整数之间的除法只保留整数部分。 可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。...栈 虚拟机栈 栈帧的区别 栈是一种特殊的数据结构,它具有“先进后出”的特点,栈可以通过入栈(push)和出栈(pop)操作进行数据的存储和读取。...虚拟机栈是Java虚拟机所使用的栈结构,用于存储方法执行时的数据和指令等信息。在Java程序运行时,每个线程都会有一个对应的虚拟机栈。 栈帧是虚拟机栈中的一个元素,它用于存储一个方法的执行状态。...在一个方法被执行时,虚拟机就会创建一个对应的栈帧,并将其压入虚拟机栈中。当这个方法执行完毕后,对应的栈帧也会从虚拟机栈中弹出,恢复到调用该方法的上一个方法的执行状态。...因此,栈和虚拟机栈都是数据结构,用于存储数据和指令等信息,但是前者通常是指物理内存中的一块区域,而后者则是Java虚拟机的一种抽象结构。
特点: 栈是一种快速有效的分配存储方式,访问速度仅次于程序计数器 JVM 直接对虚拟机栈的操作只有两个:每个方法执行,伴随着入栈(进栈/压栈),方法执行结束出栈 栈不存在垃圾回收问题 栈中可能出现的异常...每个线程都有自己的栈,栈中的数据都是以栈帧(Stack Frame)的格式存在 在这个线程上正在执行的每个方法都各自有对应的一个栈帧 栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息...2.3 栈运行原理 JVM 直接对 Java 栈的操作只有两个,对栈帧的压栈和出栈,遵循“先进后出/后进先出”原则 在一条活动线程中,一个时间点上,只会有一个活动的栈帧。...即只有当前正在执行的方法的栈帧(栈顶栈帧)是有效的,这个栈帧被称为当前栈帧(Current Frame),与当前栈帧对应的方法就是当前方法(Current Method),定义这个方法的类就是当前类(Current...根据字节码指令,往操作数栈中写入数据或提取数据,即入栈(push)、出栈(pop) 某些字节码指令将值压入操作数栈,其余的字节码指令将操作数取出栈。
毕竟计算机不认识你的java程序。因为它不是人。 要理解这个字节码,首先要明白,方法的执行就是操作栈帧,栈帧中包含了操作数栈和本地变量表这两个概念。...本地变量表,就是保存了方法的变量,比如第0位置的args参数,第1位置的i参数。操作数栈你可以理解对数据进行压栈出栈操作。 bipush 8就是把8压到操作数栈中。...istore_1就是操作数栈出栈,存到本地变量表的第1位置的i,就是代码中的i = 8; iload_1,就是变量表中第一个位置的i压栈到操作数栈顶,此时栈顶为8 iinc 1 by 1,就是变量表中第一个位置的...0 bipush 8 把8压到操作数栈中 2 istore_1 操作数栈出栈,存到本地变量表的第1位置的i,就是代码中的i = 8; 3 iinc 1 by 1 变量表中第一个位置的i加1,那么变量表最终...从表面上看就是上文说的,i=i++先赋值再加1,i=++i先加1再赋值。 曾经的那个面试官,你在哪儿,我来回答你当年那个问题,可能你并不知道也停留在表面吧。
---- 1.什么是函数栈帧 函数栈帧( stack frame )就是函数调用过程中在程序的调用栈( call stack )所开辟的空间,这些空间是用来存放: 函数参数和函数返回值...在经典的计算机科学中,栈被定义为一种特殊的容器,用户可以将数据压入栈中(入栈 push ),也可以将已经压入栈中的数据弹出(出栈,pop ),但是栈这个容器必须遵守一条规则: 先入栈的数据后出栈 (First...压栈操作使得栈增大,而弹出操作使得栈减小。 在经典的操作系统中, 栈总是向下增长(由高地址向低地址) 的。... 基本知识 1.每一次函数调用,都要为本次函数调用开辟空间,就是函数栈帧的空间。...2.这块空间的维护是使用了两个寄存器:esp ebp,ebp记录的是栈底的地址,esp记录的是栈顶的地址。 3.函数栈帧的创建和销毁过程,在不同的编译器上实现的方法大同小异。
2,方法区 方法区用于存储被虚拟机加载的类信息、常量、static变量等数据 3,Java栈 **每条线程有自己的工作内存(Java栈)**不同线程之间无法直接访问对方工作内存中的变量。...每一个方法从调用直至执行完成的过程,就对应这一个栈帧在虚拟机中从入栈到出栈的过程。...Java栈用于实现方法调用,每次方法调用就对应栈中的一个栈帧,栈帧包含局部变量表、操作数栈、方法接口等于方法相关的信息,栈中的数据当没有引用指向数据时,这个数据就会消失。...4,本地方法栈 本地方法栈保存的是本地方法的调用。 问题扩展: 线程安全问题就是,多个线程的工作内存同时对堆中同一个数据的修改,使用Java锁避免线程安全问题。...application,他在所有的应用程序中都有效,也就是当服务器开始到服务器结束这段时间,application作用域中存储的数据都是有效的,同样可以通过setAttribute赋值和getAttribute
上一篇 : 栈论 : 递归与栈式访问,如何用栈实现所有递归操作(函数调用底层篇) 2.用基础知识实现递归转栈式访问 基于以上几点,我们怎么把所有的递归都用栈这个数据结构实现呢?...在这里,我们把栈的元素直接设计为节点,因为节点的信息已经够我们完成所有操作(只有visit操作而已); 1.如果把栈帧的入栈想成函数调用,出栈想成函数返回,那么当栈为空的时候,函数调用就结束了。...于是有了下面1处的判断栈是否是空的 2.你可能会问:子函数都没调用完,2处怎么就把父函数的栈帧出栈了呢?...在下面需要对栈帧做的所有操作只有visit,也就是访问他的节点,子函数栈帧入栈前(调用子函数)就可以把父函数的所有操作在3处完成了,没有其他操作要等待子函数栈帧出栈(返回)接着做,而且子函数的栈帧已经包含所有操作需要的信息了...(BiTree),所以2处父栈帧直接出栈。
地址空间与物理内存 (1)地址空间与物理内存是两个完全不同的概念,真正的代码及数据都存在物理内存中。...如图: 二、栈帧的建立 首先要明白几个地方:每一个函数都有自己的栈帧空间,并且独占自己的栈帧空间, 当前正在运行的函数的栈帧总是在栈顶。...「注:函数栈帧的大小并不固定,一般与其对应函数的局部变量多少有关。函数运行过程中,其栈帧大小也是在不停变化的。除了与栈相关的寄存器外,我们还需要记住另一个至关重要的寄存器。」...这其中也许有进栈、出栈的动作,栈指针ESP也会上下移动,但EBP是保持不变的。这意味着我们可以一直用[EBP+…]找到第一个参数,而不管在函数中有多少进出栈的动作。...进栈和出栈操作的次数必须保持平衡。 在程序控制权返回到调用者main)后,这时,传递给fun的参数通常已经不需要了。
很多人会误以为Java内存区域和内存模型是同一个东西,其实并不是。 Java内存区域是指 JVM运行时将数据分区域存储 ,简单的说就是不同的数据放在不同的地方。通常又叫 运行时数据区域。...3、Java虚拟机栈 虚拟机栈 描述的是 Java 方法执行的内存模型: 每个方法在执行的同时都会创建一个栈帧(Stack Frame,是方法运行时的基础数据结构)用于存储局部变量表、操作数栈、动态链接...每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。 虚拟机栈是每个线程独有的,随着线程的创建而存在,线程结束而死亡。...在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法。 1)局部变量表 局部变量表是存放方法参数和局部变量的区域。...2)操作数栈 一个先入后出的栈。 当一个方法刚刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈/入栈操作。
领取专属 10元无门槛券
手把手带您无忧上云