精华内容
下载资源
问答
  • 数据结构:先进后出 线程运行时所需要的内存空间 ...内存越大,线程数越少,因为物理内存是固定的,如果栈内存越大,线程数越少 方法内的局部变量是否线程安全? 主要看这个变量共享的还是私有的,答案..

    1. 数据结构:先进后出

    2. 线程运行时所需要的内存空间
      一个栈内可以看作是由多个栈帧组成(一个栈帧表示一次方法的调用,每个方法运行时需要的内存)
      栈帧(方法参数,局部变量,返回地址)
      出栈:释放栈帧所占用的内存空间,方法调用结束就释放内存
      每个线程运行时只能有一个活动栈帧,对应当前正在执行的代码

    3. 垃圾回收是否涉及栈内存?
      不会

    4. 栈内存越大越好吗?
      内存越大,线程数越少,因为物理内存是固定的,如果栈内存越大,线程数越少

    5. 方法内的局部变量是否是线程安全?
      主要看这个变量是共享的还是私有的,答案是私有的,因为一个线程对应着一个栈,一个方法调用产生一个栈帧,就算该线程停了,另一条线程运行,栈中所调用的方法也是他自己的,也就是线程私有,所以不会存在线程安全问题,(如果定义变量为static,则会让两条线程共享变量,就会产生安全问题)[如果加了static还想线程安全可以加volatile修饰]
      想要判断一个变量是否是线程安全的,如果方法内局部变量没有逃离方法的作用范围,他是线程安全的,如果逃离了,并引用了局部变量(被返回了,对象当作参数等)
      6.栈内存溢出情况:
      1,栈帧过多 ,方法递归调用没有设置一个正确的调用条件

    private static int count;
    	    public static void main(String[] args) {
    	        try{
    	            method();
    	        }catch (Throwable e){
    	            e.printStackTrace();
    	            System.out.println(count);
    	        }
    	    }
    
    	    private static void method() {
    	        count++;
    	        method();
    	    }
    	    //stackOverFlowError   栈内存溢出
    
    

    2.栈帧过大,大过栈内存(情况比较少)
    3.第三方工具类也有可能出现内存溢出的情况(两个类之间的循环引用)

    展开全文
  • 栈内存溢出

    千次阅读 2016-12-28 11:07:02
    补充下我谈一下自己的看法(我们的讨论限定于...那么对一个线程而言,会先达到线程的深度限制(StackOverFlowError)还是线程的栈内存限制(OOME)呢?深度在栈内存足够的情况下,不能一直去增加桢来加深吗? 2

    补充下我谈一下自己的看法(我们的讨论限定于比较常见的HotSpot VM):
    1.线程栈内存:线程创建时,线程占用的栈内存大小可以通过-Xss设置,那么我们可以认为 栈的深度X栈桢所占用内存=线程的栈内存大小。那么对一个线程而言,是会先达到线程的栈深度限制(StackOverFlowError)还是线程的栈内存限制(OOME)呢?栈深度在栈内存足够的情况下,不能一直去增加栈桢来加深吗?

    2.JVM栈内存:对于JVM而言,其可用总内存是固定的(是多少呢?),减掉方法区的内存大小和堆内存大小,就可以大概认为剩下的是JVM的栈内存大小;但实际上JVM貌似没有显示的参数可以去设置栈内存大小,这个是令我对栈内存溢出困惑的根源。既然他没有显示的大小,那我怎么应证不是堆内存溢出,不是方法区内存溢出,而是栈内存溢出呢?







    1.栈内存从概念上分 “线程的栈内存” 和 “JVM的栈内存” 两种。
    2.线程的栈内存:每新建一个线程时,会分配给这个线程一个栈内存初始值,最大的大小可通过 -Xss 来设置。线程占有的栈内存大小,通过不断执行方法,生成局部变量等操作,栈桢不断增加,该线程的栈内存也不断被使用。最终达到 -Xss 的值时,会抛出StackOverFlowError。其实这里就是线程的栈内存溢出,背后的概念与 OOME 是一样的,只是jvm设计者取的名字不一样而已。
    3.JVM的栈内存:当一个jvm进程启动时,会不断消耗 native memory。我们可以通过参数 -Xmx 等来设置堆内存、方法区内存的最大值,当达到阀值时,jvm就会报OOME。但是栈内存大小,则是物理机器的native memory,其上限就是native memory的上限。不断建线程消耗native memory待尽时,就会报OOME。(这一点我没有实际验证过,因为我不断新建线程的后果是电脑死机)


    作者:chiukong
    链接:https://www.zhihu.com/question/28637033/answer/41677862
    来源:知乎
    著作权归作者所有,转载请联系作者获得授权。



    单线程下,xss设置太小,或者定义太多的本地变量(递归)都会导致stackoverflow。多线程下,通过不断创建新的线程就会导致oom。
    -----------------------
    1、那么对一个线程而言,是会先达到线程的栈深度限制(StackOverFlowError)还是线程的栈内存限制(OOME)呢? 是stackoverflow,楼主随便写个递归函数试试便知。
    2、摘抄周总的一句话,栈内存溢出中的stackoverflow和oom,当栈空间无法继续分配时,到底是内存太小,还是已使用的栈空间太大,其本质只是对同一件事情的两种描述而已。不知道楼主的疑惑是否在这里。


    作者:xiaomai mai
    链接:https://www.zhihu.com/question/28637033/answer/41569566
    来源:知乎
    著作权归作者所有,转载请联系作者获得授权。



    outofmemory:out of=不够,不足,memory=内存
    ok,意思就是内存不够,那你搞到jvm内存不够就可以了啊。
    现在我来回答你的问题“怎么产生”:
    要StackOverflowError:
    static int level = 1;
    static void callback(){
        level++;
        System.out.println("level:"+level);
        callback();
    }
    
    要outOfMemory:
    static ArrayList<byte[]> list = new ArrayList<byte[]>();
    static void callback(){
        while(true){
            list.add(new byte[1024*1024]);
            System.out.println(list.size());
        }
    }

    写个不结束的递归函数很快就会栈益出。不断的去new新对象,堆也很快益出


    栈溢出有两种,一种是stackoverflow,另一种是outofmemory,前者一般是因为方法递归没终止条件,后者一般是方法中线程启动过多。





    在《java虚拟机规范中文版》第二章第五节中有这么几句话:
    1.如果线程请求分配的栈容量超过java虚拟机栈允许的最大容量的时候,java虚拟机将抛出一个StackOverFlowError异常。
    2.如果java虚拟机栈可以动态拓展,并且扩展的动作已经尝试过,但是目前无法申请到足够的内存去完成拓展,或者在建立新线程的时候没有足够的内存去创建对应的虚拟机栈,那java虚拟机将会抛出一个OutOfMemoryError异常。


    刚看到题主在问题下的评论,xss分配的应该是每个线程的栈大小,线程数量和整个进程的大小是由操作系统来限制的。
    对于单个线程,栈内存容量减小,或者变量表深度增大,就会造成StackOverFlow,这点我跟题主想的一样。
    至于是堆内存溢出还是方法区内存溢出还是栈内存溢出,其实可以用一些工具比如
    JConsole来监视。





    展开全文
  • 文章目录Pre栈内存溢出能依托之前的办法解决吗?Code运行代码后分析异常报错信息的调用 Pre 之前的文章,我们分析了Metaspace...首先明确一点,栈内存溢出跟堆内存是没有关系的,因为他的本质一个线程的中压

    在这里插入图片描述


    Pre

    之前的文章,我们分析了Metaspace区域是如何内存溢出的,同时还带着大家分析了一下内存快照。

    今天这篇文章,我们就带大家分析一下JVM栈内存溢出的时候,怎么来解决。


    栈内存溢出能依托之前的办法解决吗?

    首先大家思考一个问题:栈内存溢出能按照之前的方法解决吗?

    也就是说,GC日志、内存快照,这些东西对解决栈内存溢出有帮助吗?

    首先明确一点,栈内存溢出跟堆内存是没有关系的,因为他的本质是一个线程的栈中压入了过多方法调用的栈桢,比如几千次方法调用的几千个栈桢。

    此时就导致线程的栈内存不足,无法放入更多栈桢了。

    所以GC日志对你有用吗?

    没用!因为GC日志主要是分析堆内存和Metaspace区域的一些GC情况的,就线程的栈内存和栈桢而言,他们不存在所谓的GC。

    如果大家还记得之前我们画的图,就应该知道,调用一个方法时在栈里压入栈桢,接着执行完整个方法,栈桢从栈里出来,然后一个线程运行完毕时,他的栈内存就没了。

    所以本身这块内存不存在所谓的GC和回收,调用方法就给栈桢分配内存,执行完方法就回收掉那个栈桢的内存。

    那么内存快照呢?

    内存快照主要是分析一些内存占用的,同样是针对堆内存和Metaspace的,所以对线程的栈内存而言,也不需要借助这个东西。


    Code

    在这里插入图片描述
    使用的JVM参数如下:

    -XX:ThreadStackSize=1m
    
    -XX:+PrintGCDetails
    
    -Xloggc:gc.log
    
    -XX:+HeapDumpOnOutOfMemoryError
    
    -XX:HeapDumpPath=./
    
    -XX:+UseParNewGC
    
    -XX:+UseConcMarkSweepGC
    

    运行代码后分析异常报错信息的调用栈

    接着我们运行代码让他产生栈内存溢出的报错,如下:

    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    at com.artisan.demo.jvm.Demo2.work(Demo2.java:13)
    
    

    实际上我们会在这里看到大段大段的如上所示的异常,也就是说,他会直接告诉你这个栈内存溢出的问题,是因为你拼命的调用Demo2这个类的work()方法时发生的。

    因此就栈内存溢出而言,我们定位和解决问题非常的简单,你只要把所有的异常都写入本地日志文件,那么当你发现系统崩溃了,第一步就去日志里定位一下异常信息就知道了。

    比如,昨天我们通过异常信息直接定位出来是Metaspace区域出的异常,然后分析一下GC日志就完全知道发生溢出的全过程,接着再分析一下MAT的内存快照,就知道是哪个类太多导致的异常。

    今天的栈内存溢出,我们直接去日志文件里看到是栈内存溢出:Exception in thread “main” java.lang.StackOverflowError。

    此时心里就有数了,然后直接看一下对应报错的方法就可以了。知道是哪个方法,直接去代码中定位问题即可。


    小结

    学习了一下栈内存溢出的解决办法,其实这是最容易定位和解决的一种异常了,大家只要有一个好习惯,就是把异常信息都写入本地日志文件,系统崩溃了直接看日志就知道怎么回事了。
    在这里插入图片描述

    展开全文
  • 栈内存是如何被编译器维护的

    千次阅读 2017-06-27 15:43:22
    在程序运行期间由编译器来管理栈内存吗?怎么可能! 以函数调用时的出入为例:原来编译器在编译函数调用代码时,不仅编译成call指令,还会在call指令之前添加若干入栈指令:push,在函数返回时会添加对应 的出栈...
    栈内存是如何被编译器维护的


    我们一直听说“栈内存由编译器维护”,那是如何维护的呢?是在程序运行期间由编译器来管理栈内存吗?怎么可能!
    以函数调用时的出入栈为例:原来编译器在编译函数调用代码时,不仅编译成call指令,还会在call指令之前添加若干入栈指令:push,在函数返回时会添加对应的出栈指令:pop。这部分是程序员无法控制的,因此叫作栈内存由编译器维护,并非运行期间维护的,而是编译期间就提前决策千里之外了^-^


    :在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。


    :一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。


    关于进程空间的概念请阅读:Linux进程空间与虚拟地址的好处
    展开全文
  • 内存栈内存

    2020-11-17 20:46:28
    内存栈内存 前言 上网搜了很多关于堆和相关的问题,也看了很多的关于堆和的博客,看了这么多感觉都差不多的,整了半天也没大搞懂,然后看到一则评论说:“javacript范类型。知道咋用就行了,别把简单...
  • 内存中的分配

    2018-01-19 20:12:05
    什么以前的在Linux下编程不都连续的从低地址开始分配内存空间吗。也不墨迹区区搜了一下,答案如下:我看的LiteOS泡在ARM M4上的,这个mcu的内存分配就是在内存中自减的形式。内存地址:小 ————————...
  • 程序员大多都碰到过内存溢出溢出,最常见的结果导致程序Crash,有时候也有可能因为覆盖上的信息导致程序执行一些意想不到的逻辑,这种情况往往比起Crash更加糟糕。 在阅读本文之前,最好熟悉<<你了解...
  • 我们编程时经常用到的数据结构,在计算机组成原理中,竟然会提到地址增长方向与内存地址增长方向相反,那这为什么呢? 当我们定义一个时,我们事先不可预料最终的大小的,因为我们总是会根据需要向...
  • 引言:我们都熟知并且常用JS变量的声明以及初始化(赋值),比如一行极其简单的代码var str = '我字符串',那么这行代码执行的时候发生了什么呢?再比如var obj = {name: 'reslicma'}又发生了什么?他们一样吗?请...
  • 如果想了解变量的有效范围、对象的建立、内存的管理、线程和异常的处理、则认识堆、栈是很重要的。 先说说栈吧,这里就不详细说栈,堆的概念了,只是谈谈在java中是如何分配栈和堆的空间的。 在java中是把局部变量...
  • 1、堆在内存的全局存储空间中,用于程序动态分配和释放的内存块称为自由...栈是用来存放局部变量、函数的参数以及调用函数和被调用函数的联系的内存池。它是一种先进后出的压入弹出式的数据结构。栈内存由编译器在需
  • 方法区里存常量 那一个类的方法和一个类的属性都在方法区吗
  • 当时忽然意识到,内存泄露这个问题一直被我忽略,因为用的java/C#,这些语言中都有内存自动回收的机制,我突然发现自己对这个问题竟然一无所知。面试中的就是下面这个: // 你能检查出"内存泄露"吗? public ...
  • 当我们在用C++做底层驱动的时候,经常会遇到内存不足的警告,究其原因,往往因为内存出现溢出,泄露或者越界等原因。那么他们之间有什么联系吗? 内存溢出(out of memory)指程序在申请内存时,没有足够的内存...
  • 首先我们要了解我们为什么要学习java虚拟机的内存管理,不是java的gc垃圾回收机制都帮我们...Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如下图所示:我认为我们最重要的了解栈内存(Stack)和堆内存
  • 计算机中的堆和和(物理内存上的解释)

    千次阅读 多人点赞 2017-11-25 14:06:08
    编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有本质上解释这堆和栈是什么。我仅有高级语言编程经验,没有看过对此更清晰的解释。我的意思是我理解什么是栈,但是它们到底是什么,在...
  • 什么是栈

    2020-05-22 17:38:47
    说白了就是内存中的一块地址,用来存储类似于变量,函数之类的程序需要它,但放到内存地址中太不容易找的东西。你明白了吗?阅读 10万+...
  • 为了防止歧义,可以换个说法:Java对象实例和数组元素都在堆上分配内存的吗? 答:不一定。满足特定条件时,它们可以在(虚拟机)上分配内存。 JVM内存结构很重要,多多复习 这和我们平时的理解可能有些...
  • 为了防止歧义,可以换个说法:Java对象实例和数组元素都在堆上分配内存的吗? 答:不一定。满足特定条件时,它们可以在(虚拟机)上分配内存。 JVM内存结构很重要,多多复习 这和我们平时的理解可能有些不同...
  • 1、堆是线程共享的内存区域,栈是线程独享的内存区域。 2、堆中主要存放对象实例,栈中主要存放各种基本数据类型、对象的引用。 但是其实以上两个结论并不是完全正确的。 在解释原因之前首先抛出个问题:Java对象...
  • 在JVM的内存结构中,比较常见的两个区域就是堆内存栈内存(如无特指,本文提到的均指的虚拟机),关于堆和的区别,很多开发者也如数家珍,有很多书籍,或者网上的文章大概都这样介绍的: 堆线程...
  • 随着JIT编译期的发展与逃逸分析技术逐渐成熟,上分配、标量替换优化技术将会...如果JIT经过逃逸分析,发现有些对象没有逃逸出方法,那么有可能堆内存分配会被优化成栈内存分配。 这里借鉴一下大佬的图片: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,021
精华内容 408
关键字:

栈是内存吗