首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于检查StackOverflowException的计算方法调用堆栈大小

用于检查StackOverflowException的计算方法调用堆栈大小
EN

Stack Overflow用户
提问于 2013-04-17 16:42:17
回答 5查看 4.9K关注 0票数 11

今天早上我回答了一个关于StackoverflowException的问题。该人员已询问Stackoverflow异常何时发生

请参阅此链接Simplest ways to cause stack overflow in C#, C++ and Java

所以我的问题是,有没有什么方法可以在我们的程序中动态计算方法调用堆栈的大小,然后在调用一个方法之前进行检查,检查方法调用堆栈是否有空间容纳它,以防止StackOverflowException。

由于我是一个java人,我正在寻找java,但也在寻找与没有任何编程语言基础的概念相关的解释。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-05-20 11:54:12

对于32位JVM,JVM可用的总内存约为2-4 4GB,对于64位JVM,总内存约为2-4 4GB的平方(约4-16EB)。JVM将其内存拆分为:

  1. 堆内存(通过JVM选项-Xms和JVM控制分配

代码语言:javascript
复制
- constructed object and array instances
- static classes and array data (including contained object/array instances)
- thread instances (object instances, runtime data & metadata including thread object monitor lock references)

  1. Non-Heap Memory

代码语言:javascript
复制
- aggregate stack memory  
    - per-thread stack memory **(per-thread allocation controlled via JVM option -Xss)**: method call frames, arguments, return values, locally declared primitives & references to objects

代码语言:javascript
复制
- static constants (primitives)
- String instance pool
- java code: loaded classes and metadata
- JVM internal-use memory (JVM code and data structures) 

请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/management/MemoryMXBean.htmlhttp://www.yourkit.com/docs/kb/sizes.jsp

有没有什么方法可以用来在我们的程序中动态计算方法调用堆栈的大小

  1. 在Java /Java中没有标准的方法来获取每个线程堆栈的实际内存使用量。
  2. 有一些标准的方法来获取聚合的非堆内存:MemoryMxBean.getNonHeapMemoryUsage()。exception
  3. There是获得调用堆栈而不占用内存的标准方法:ThreadInfo.getStackTrace()

ThreadMxBean.getThreadInfo() & StackOverflow

我建议你不要按照问题中的建议去做,因为:

你不能没有一些复杂的特定于JVM的API来检测/内省动态线程堆栈的内存使用情况-在哪里你会发现这样的API??

  • The每线程堆栈通常相对于整个JVM只消耗很少的内存,所以通常很容易分配足够的内存来适应你的算法(例如,默认的128KB堆栈大小对于Windows64bitJVM,而2 2GB的内存可能已经被预算给整个JVM)

  • 它的能力将非常有限:如果你的逻辑实际上需要调用一个方法,但是你不能因为内存不足,那么你的程序在这一点上就会崩溃。一个StackOverflow异常实际上是你尝试做的最好的response.

  • What,可以是一个反设计反模式

一个“正确”的方法应该是指定程序需求,指定所需的运行时环境(包括最小/需要的内存!),并相应地设计您的程序以获得最佳的性能和内存。usage.An反模式是在设计和开发期间不适当地考虑这些事情,而只是想象一些运行时内省魔法可以覆盖这一点。可能存在一些(罕见的!)高性能要求的应用程序,需要在运行时重新安排算法以精确匹配所发现的资源-但这是复杂、丑陋的& expensive.And即使如此,它可能会更好地从"-Xss“参数在宏观级别驱动动态算法更改,而不是从代码中某个位置的确切堆栈内存消耗在微观级别驱动动态算法更改。

票数 10
EN

Stack Overflow用户

发布于 2013-04-26 21:10:53

我希望我猜到你真正想问的是什么。一开始,我以为你是在问你的通话深度是多少。换句话说,基于您当前的方法环境,我认为您想知道触发此异常的可能性有多大。然后我决定你真的很想知道你有多少堆栈深度可以玩。在这种情况下,这里似乎有另一个堆栈溢出问题可以解决这个问题。What is the maximum depth of the java call stack?

这将告诉您如何将其设置为java命令行参数(设置为java,而不是您的程序)。

无论哪种方式,我想指出的是,堆栈溢出主要发生在我进行无休止的递归时。我写了一些方法(当然是错误的),它们会调用自己,并打算在问题解决时停止,但不知何故,终止条件从未达到。这会将方法调用一遍又一遍地放到堆栈上,直到超过最大值为止。这不是我想要的。

我希望这能有所帮助。

票数 5
EN

Stack Overflow用户

发布于 2013-05-20 12:04:28

据我所知,Java中的堆栈限制是相当抽象的,不是用来测量的。事实上,我怀疑堆栈的大小会因机器的不同而不同,这取决于几个因素,比如内存。

除了无限循环/递归,我从来没有得到过抛出堆栈溢出异常的程序。我正在挠头,试图弄清楚如何在没有无限循环的情况下抛出堆栈溢出异常。如果您的程序调用了那么多方法,那么它很可能会同时创建对象,并且您更有可能收到OutOfMemory错误,而不是没有无限循环的堆栈溢出异常。

事实上,堆栈限制会限制你正常工作的能力,这到底是什么意思呢?Java有内存限制,可以应对过度使用资源的情况。堆栈溢出的目的是捕获已经失控并需要捕获的循环/递归。

我想说的是:如果堆栈溢出异常困扰着你的单元测试,你应该检查那些循环/递归函数是否有一些失控的行为。调用堆栈非常、非常长,我怀疑您是否自然地达到了它。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16055441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档