精华内容
下载资源
问答
  • 虚拟机栈动态扩展

    千次阅读 2019-05-07 20:27:19
    虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从电泳直至执行完成的过程,就对应着一个栈帧在...

    虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从电泳直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

    动态扩展

    函数调用需要使用栈,如果函数调用链很深(递归的时候很常见),栈的空间不够就会出StackOverflow。
    动态扩展就是在栈空间不够的时候,自动加大栈的空间,避免StackOverflow,JVM是没有实现这个功能的。
    动态栈通常有两种方法:Segmented stack和Stack copying。
    Segmented stack可以简单理解成一个双向链表把多个栈连接起来,一开始只分配一个栈,这个栈的空间不够时,就再分配一个,用链表一个一个连起来。
    Stack copying就是在栈不够的时候,分配一个更大的栈,然后把原来的栈复制过去。

    展开全文
  • java虚拟机栈

    2021-09-22 15:14:40
    java虚拟机栈1.java虚拟机栈2.栈帧(Stack Frame)3.局部变量表4....如果虚拟机栈可以动态扩展,但是扩展时无法申请到足够的内存,就会抛出OutOfMemeryError异常; java虚拟机栈描述的是java方法执行的内存

    1.java虚拟机栈

    1. java虚拟机栈是线程私有的, 生命周期与线程相同。
    2. 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverFlow异常;
      如果虚拟机栈可以动态扩展,但是扩展时无法申请到足够的内存,就会抛出OutOfMemeryError异常;
    3. java虚拟机栈描述的是java方法执行的内存模型:每个方法执行的同时会创建一个栈帧。

    2.栈帧(Stack Frame)

    1. 栈帧(Stack Frame)是用于支持虚拟机进行方法调用和方法执行的数据结构。它是虚拟机运行时数据区中的java虚拟机栈的栈元素。
    2. 栈帧用于存储一个方法的局部变量表、操作数栈、动态链接、方法出口等信息。
      每个方法被调用直至执行完成的过程对应一个栈桢在虚拟机中从入栈到出栈的过程。

    注意
    在编译程序代码的时候,栈帧中需要多大的局部变量表内存,多深的操作数栈都已经完全确定了。
    因此一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。

    栈结构图
    栈结构图

    注意
    在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法。
    执行引擎运行的所有字节码指令都只针对当前栈帧进行操作。

    3.局部变量表

    1. 局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。
      并且,在Java编译为Class文件时,就已经确定了该方法所需要分配的局部变量表的最大容量。
    2. 局部变量表存放了编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double「String是引用类型」),对象引用(reference类型)和returnAddress类型(它指向了一条字节码指令的地址)。

    关于returnAddress:
    在 JVM 中,数据分为两大类:primitive types (原生类型)和 reference types(引用类型)。
    原生数据类型包括:numeric types, boolean type, returnAddress type。其中 returnAddress 数据只存在于字节码层面,与编程语言无关,也就是说,我们在 Java 语言中是不会直接与 returnAddress 类型的数据打交道的。
    returnAddress 类型的值是指向字节码的指针,不管是物理机还是虚拟机,运行时内存中的数据总归可分为两类:代码,数据。对于冯诺依曼结构的计算机,指令数据和数值数据都存储在内存中,而哈弗结构的计算机,将程序指令与数据分开存储。
    对于 JVM 来说,程序就是存储在方法区的字节码指令,而 returnAddress 类型的值就是指向特定指令内存地址的指针。
    JVM支持多线程,每个线程有自己的程序计数器(pc register),而 pc 中的值就是当前指令所在的内存地址,即 returnAddress 类型的数据,当线程执行 native 方法时,pc 中的值为 undefined。

    注意
    "基本数据和对象引用存储在栈中。"这种说法只针对局部变量。如果是成员变量,或者定义在方法外对象的引用,它们存储在堆中。

    4. 变量槽(Variable Slot)

    1. 局部变量表的容量以变量槽为最小单位,每个变量槽都可以存储32位长度的内存空间,例如boolean、byte、char、short、int、float、reference。
    2. 对于64位长度的数据类型(long、double),虚拟机会以高位对齐方式为其分配两个连续的Slot空间,也就是相当于把一次long和double数据类型读写分割成为两次32位读写。

    5.reference(对象实例的引用)

    具体参见链接https://blog.csdn.net/wangdong5678999/article/details/68931538/
    在这里插入图片描述

    6. 动态链接

    每个栈帧都包含一个指向运行时常量池中该栈帧所述方法的引用,持有这个引用是为了支持方法调用过程中的动态链接

    在类加载阶段中的解析阶段会将符号引用转为直接引用,这种转化也成为静态解析
    另外的一部分将在每一次运行时期转化为直接引用,这部分成为动态链接

    方法区里静态解析式不完全正确,要在运行期间栈帧进栈的时候动态连接到真实的类和方法。

    参考: 栈帧中动态链接的理解

    7. 方法出口

    当一个方法开始执行后,只有两种方式可以推出这个方法:
    方法返回指令:执行引擎遇到一个方法返回的字节码指令,可能会有返回值传递给上层的方法调用者,这种退出方式称为正常完成出口
    异常退出: 在方法执行过程中遇到了异常,并且没有处理这个异常,就会导致退出。

    无论采用哪种退出方式,方法推出后都需要返回到方法被调用的位置程序才能继续执行,方法返回是可能需要在栈帧中保存一些信息。

    一般来说,正常退出时,调用者的PC计数器的值可以作为返回地址(returnAddress type),栈帧会保存这个计数器值。
    然而方法异常退出时,返回地址需要通过异常处理器来确定,栈帧中一般不会保存这部分信息。

    展开全文
  • 虚拟机栈

    2020-07-06 21:10:28
    每个方法发执行都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、方法返回地址、动态链接、一些附加信息每个方法的调用直至执行完过程,对应着一个栈帧在虚拟机栈中找到出栈的过程 局部变量表 局部...

    Java虚拟机栈

    虚拟机栈是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型;每个方法发执行都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、方法返回地址、动态链接、一些附加信息每个方法的调用直至执行完过程,对应着一个栈帧在虚拟机栈中找到出栈的过程
    在这里插入图片描述

    局部变量表

    局部变量表存放编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference)和returnAddress类型局部变量表所需要的内存空间在编译期完全分配,方法在运行期间v不会改变就局部变量表的大小。

    操作数栈

    虚拟机把操作数栈作为它的工作区——大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。

    虚拟机栈的两种异常

    一、如果线程的请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常(栈溢出异常)
    二、如果虚拟机栈可以动扩展时无法申请到足够内存,就会抛出OutOfMemoryError异常(内存不足)

    一起学习交流的可以加下面的QQ群:

    515131162

    点击链接加入群聊【Java从入门到放弃】:https://jq.qq.com/?_wv=1027&k=pYNPNi6q

    展开全文
  • 一、在Java虚拟机规范中,对... (2)如果虚拟机栈可以动态扩展(当前大部分的 Java 虚拟机都可动态扩展,只不过 Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemory...

    一、在Java虚拟机规范中,对【虚拟机栈】这个内存区域规定了两种异常状况:

          (1)如果线程请求的【栈深度】大于虚拟机所允许的深度,将抛出StackOverflowError异常;

          (2)如果虚拟机栈可以动态扩展(当前大部分的 Java 虚拟机都可动态扩展,只不过 Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。

          (3)与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowError 和OutOfMemoryError 异常。

    二、对于虚拟机栈和本地方法栈 如果在多线程的情况下是可能出现OOM的,下边就是一个单线程的案例。演示一下:

    /**
     * 设置 VM Args: -Xss128k
     */
    public class JavaVMStackSOF {
    
        private int stackLength = 1;
    
        //反复调用
        public void stackLeak(){
            stackLength++;
            stackLeak();
        }
    
        public static void main(String [] args){
            JavaVMStackSOF oom = new JavaVMStackSOF();
            try {
                oom.stackLeak();
            }catch (Throwable e){
                System.out.println("stack length:" + oom.stackLength);
                throw e;
            }
        }
    }
    

    要设置VM Args: -Xss128k(设置栈为128k),结果如下:

    stack length:995
    Exception in thread "main" java.lang.StackOverflowError
        at com.adonai.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
        at com.adonai.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:13)

    结果表明:在单线程下,无论是由于栈帧太大,还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是StackOverflowError异常,而不是OOM。

    三、如果测试时不限于单线程,通过不断地建立线程的方式倒是可以产生内存溢出异常。

          自己可以创建多个线程,进行测试

          但是:由于在Windows 平台的虚拟机中, Java 的线程是映射到操作系统的内核线程上的,所以多线程代码执行时有较大的风险,可能会导致操作系统假死。

         不过结果肯定是,多线程的情况下,是会出现OOM的!

    原理如下:

       为什么多线程的情况下就会产生OOM,这样产生的内存溢出异常与栈空间是否足够大并不存在任何联系,或者准确地说,在这种情况下,给每个线程的栈分配的内存越大,反而越容易产生内存溢出异常。

      原因其实不难理解,操作系统分配给每个进程的内存是有限制的,譬如 32 位的 Windows 限制为 2GB。虚拟机提供了参数来控制 Java 堆和方法区的这两部分内存的最大值。剩余的内存为 2GB(操作系统限制)减去 Xmx(最大堆容量),再减去 MaxPermSize(最大方法区容量),程序计数器消耗内存很小,可以忽略掉。如果虚拟机进程本身耗费的内存不计算在内,剩下的内存就由虚拟机栈和本地方法栈“瓜分”了。每个线程分配到的栈容量越大,可以建立的线程数量自然就越少,建立线程时就越容易把剩下的内存耗尽。

     更简单理解的就是:有一个操作系统为2G,我们分配给两个线程,每个800M,也就还剩400M,这样的话,有一个线程不够用的话,就会在400里边申请,所以如果剩下的越多,出现OOM的可能性越小,如果每个分配950M,这样就剩100M,这样的话出现OOM的可能性就更大。如果在增加线程,系统对每一个线程非配的内存是一定的,所以剩下的内存更少,这样的话,出现OOM的可能更大,但这都是相对而说。

    遇到OOM这时候我们应该怎么做:

      如果是建立过多线程导致的内存溢出,在不能减少线程数或者更换 64 位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。

      如果没有这方面的经验,这种通过“减少内存”的手段来解决内存溢出的方式会比较难以想到。这种拆东墙补西墙的方法,还是自己意会吧。

     

     

    展开全文
  • Java虚拟机 - 虚拟机栈

    2019-09-05 16:38:28
    Java内存区域:虚拟机栈 虚拟机栈是线程私有的,它的生命周期与线程相同。 每当启动一个线程的时候,Java虚拟机都会为它分配一个Java栈。 Java栈以帧为单位保存线程的运行状态。虚拟机只会对Java栈执行两种操作: ...
  • (2)如果虚拟机栈可以动态扩展(当前大部分的 Java 虚拟机都可动态扩展,只不过 Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够 的内存时会抛出 OutOfMemoryError 异常。 (3)与
  • JVM虚拟机栈

    2020-09-12 14:55:47
    文章目录概述栈帧局部变量表 概述 虚拟机栈是线程私有的,他的生命...OutOfMemoryError:如果虚拟机栈的容量是可以动态扩展的,当栈扩展时无法申请到足够的内存会出现此异常。 栈帧 栈帧是Java虚拟机栈的栈元素,是用
  • Java虚拟机之虚拟机栈

    2020-06-27 08:02:23
    一、Java虚拟机栈是什么?? Java虚拟机栈(Java Virtual Machine Stack) ,早期也叫Java栈。每个线程在创建时都会创建一虚拟机栈,其内部保存一个个的栈帧(Stack Frame) ,对应着一次次的Java方法调用,是线程私有...
  • Java虚拟机之虚拟机栈与本地方法栈

    千次阅读 2018-08-13 21:31:45
    虚拟机栈   与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机描述的是Java方法执行的内存模型:  每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态...
  • Java虚拟机栈

    2019-08-17 16:24:15
    Java虚拟机栈 Java虚拟机栈和他所属线程的生命周期是相同的,即和线程一起创建,也一起销毁。 Java虚拟机栈是Java方法执行的内存模型。 与对象内存分配关系最紧密的是堆和栈,而其中的栈就是Java虚拟机栈。 栈帧 每...
  • Java虚拟机栈详解

    2021-01-23 22:44:38
    虚拟机栈也称为Java栈,每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame) 栈特点基本介绍 Java虚拟机栈属于线程私有,它的生命周期与线程相同(随线程而生,随线程而灭) 虚拟机栈说明了线程...
  • Java虚拟机栈 Java虚拟机栈它也是线程私有的一块内存区域,所以生命周期自然和线程相同。 每个方法在执行的时候,Java虚拟机栈都会同步生成一个栈帧,然后再将这个栈帧压入Java虚拟机栈中,所以Java虚拟机栈主要保存...
  • JAVA 虚拟机栈

    2012-08-07 20:26:47
    java 虚拟机栈,在此规定了两种异常情况: ...如果虚拟机栈可以动态扩展,当扩展是无法申请到足够的内存时会抛出OutOfMemoryError异常. 第一种情况示例分析  code:  import java.util.ArrayList; im
  • JAVA虚拟机栈

    2021-02-21 20:17:56
    Java虚拟机栈是什么? Java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈,每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用 生命周期 生命...
  • 虚拟机栈描述的是java方法执行的线程内存模型:每个方法被执行的时候,java虚拟机都会同步创建一个栈帧stack frame用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完毕的过程,...
  • Java虚拟机栈是Java运行时区域的一部分,描述的是Java线程的内存模型,每个Java方法被执行的时候,虚拟机都会创建一个栈帧(stack frame),用于存储方法执行需要的数据,比如局部变量表、操作数栈、动态链接、方法...
  • HotSport虚拟机中并不区分虚拟机栈和本地方法栈。关于虚拟机栈和本地方法栈,在Java虚拟机规范中描述了两种异常: 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。如果虚拟机在...
  • 栈中可能出现的异常 ...如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,那虚拟机将会抛出一个OutOfMemoryError异常 .
  • 第 5 章 虚拟机栈

    千次阅读 多人点赞 2020-08-12 16:23:14
    第 5 章 虚拟机栈 1、虚拟机栈概述 1.1、虚拟机栈的出现背景 文档网址 https://docs.oracle.com/javase/specs/jvms/se8/html/index.html 虚拟机栈出现的背景 由于跨平台性的设计,Java的指令都是根据栈来设计的...
  • 再聊一下JVM虚拟机栈

    2021-03-16 15:46:59
    2.OutOfMemoryError:当 Java 虚拟机动态扩展到无法申请足够内存时抛出 虚拟机栈的初衷是用来描述 Java 方法执行的内存模型,每个方法被执行的时候,JVM 都会在虚拟机栈中创建一个栈帧 栈帧 栈帧(Stack Frame)是...
  • 栈帧的调入对应着方法的调用,栈帧的弹出对应着方法的结束返回,其中,由于只有弹栈和入栈的操作,java虚拟机栈没有GC机制,但在栈空间不够时会出现StackOflowError错误,java虚拟机允许栈的大小是动态或者固定不变...
  • JVM之虚拟机栈

    千次阅读 2021-03-20 00:12:35
    虚拟机栈的作用 虚拟机栈是线程JVM中线程私有的区域。 虚拟机栈是一个先进后出的队列,当一个线程开始执行一个方法,会为该方法创建一个栈帧,压入栈中,当该方法执行完毕,再将该栈帧出栈。每一个方法被调用直至...
  • Java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行的时候,...如果Java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemo
  • Java虚拟机栈简单理解

    2017-03-01 11:42:06
    与PC寄存器一样,Java虚拟机栈也是线程私有的。每一个JVM线程都有自己的java虚拟机栈,这个栈与线程同时创建,它的生命周期与线程相同。 1.虚拟机栈的特点: “虚拟机栈”描述的是Java方法执行的内存模型: 1.每个...
  • 虚拟机栈的五道面试题 1、举例栈溢出的情况?(StackOverFlowError) 通过-Xss设置栈的大小 ...如果java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对
  • 第 5 章 虚拟机栈 1、虚拟机栈概述 -Xss512k 设置栈内存大小为512k 1.1、虚拟机栈的出现背景 文档网址 https://docs.oracle.com/javase/specs/jvms/se8/html/index.html 虚拟机栈出现的背景 由于跨平台性...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 65,353
精华内容 26,141
关键字:

虚拟机栈动态扩展