Computing method call stack size for checking Stac

2019-04-05 10:44发布

Today morning I answered a question which is related to StackoverflowException . The person has asked when Stackoverflow exception occurs

See this link Simplest ways to cause stack overflow in C#, C++ and Java

So my question is that is there any method by which we can compute the method call stacks size dynamically in our program and then applying a check before calling a method which checks whether method call stack has space to accommodate it or not to prevent StackOverflowException.

As I am a java person I am looking for java but also looking for explanation related to the concept without boundation of any programming language.

5条回答
啃猪蹄的小仙女
2楼-- · 2019-04-05 11:08

I hope I am guessing what you are really asking. At first I thought you were asking how many calls deep your call was about to be. In other words, I thought you wanted to know how likely you were to trigger this exception, based on your current method circumstances. Then I decided you really wanted to find out how much stack depth you have to play with. In that case, there is another stack-overflow question that seems to address this, here. What is the maximum depth of the java call stack?

This tells you how to set that as a java command line parameter (to java, not your program).

Either way, I'd like to point out that stack overflow has mainly happened to me when I had an endless recursion. I had written methods (by mistake, of course) that called themselves, and were meant to stop when the problem got solved, but somehow the termination condition was never reached. This puts the method invocation onto the stack over and over until the max is exceeded. Not what I had in mind.

I hope that helps.

查看更多
走好不送
3楼-- · 2019-04-05 11:09

Well, you can use something like it exists in C with Microsoft C++ compiler : a specific function (i don't remember the name) which is called automatically on each start and end function.

Also, you count the number of calls and subcalls by increment and decrement the global counter after the start function and before the end function.

For example, with Microsoft .NET , you can insert some function call to increment and decrement your global counter on each call. It's JIT designed.

You can also use a nosql database in order to store your calls.

Also, there is an another thing : use a log system that automatically trace your calls.

Also, when your call stack is full, sometimes it is caused by a recursive function. With a few lines of code and an object, you can store some propagation on each function on each call. That solution can be also used for detect in any function a special thing : "who is calling me ?"

Also, since Java is a byte-code generated, you can detect the byte-code of a function call and insert before one another function call and after one another function call in order to add your custom stack.

查看更多
狗以群分
4楼-- · 2019-04-05 11:12

I think you can use StackTrace to get method call stacks size like following

 StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
查看更多
乱世女痞
5楼-- · 2019-04-05 11:18

The total memory available to a JVM is about 2-4GB for a 32bit JVM and the square of this for a 64bit JVM (about 4-16EB). The JVM splits it's memory into:

  1. Heap Memory (allocation controlled via JVM options -Xms and -Xmx)

    • 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)
  2. Non-Heap Memory

    • 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
    • static constants (primitives)
    • String instance pool
    • java code: loaded classes and metadata
    • JVM internal-use memory (JVM code and data structures)

See http://docs.oracle.com/javase/7/docs/api/java/lang/management/MemoryMXBean.html and http://www.yourkit.com/docs/kb/sizes.jsp

Is there any method by which we can compute the method call stacks size dynamically in our program

  1. There's no standard method included in Java SE/Java EE to obtain the per-thread stack actual memory usage.
  2. There are standard methods to obtain the aggregate non-heap memory: MemoryMxBean.getNonHeapMemoryUsage(). Referring to this doesn't allow you to make dynamic in-code decisions to avoid StackOverflow exception
  3. There are standard methods to obtain the call stack without it's memory usage: Thread.getStackTrace() ThreadMxBean.getThreadInfo() & ThreadInfo.getStackTrace()

I recommend that you don't do what you suggest in the question because:

  • You can't do it without some complex JVM-specific API that instruments/introspects on dynamic thread stack memory usage - where will you find such an API??
  • The per-thread stack normally consumes a tiny amount of memory relative to the entire JVM, so it is usually easy to assign enough to suit your algorithm (e.g. default of 128KB stack size for Windows 64bit JVM whilst 2GB of memory might have been budgeted for the entire JVM)
  • It would be very limited in power: if your logic actually needed to call a method, but you couldn't due to insufficient memory, then your program would be broken at that point. A StackOverflow exception would actually be the best response.
  • What you are trying to do could be an anti-design anti-pattern.
    A "correct" approach would be to specify program requirements, specify required runtime environment (including minimum/needed memory!), and design your program accordingly for optimal performance and memory usage.

    An anti-pattern is to not think about these things appropriately during design and development and just imagine some runtime introspection magic could cover for this. There may exist some (rare!) high-performance-demanding apps which need to drastically rearrange the algorithm at runtime to exactly match the discovered resources - but this is complex, ugly & expensive.

    And even then, it would probably be better drive dynamic algorithm changes at a macro-level from the "-Xss" parameter, rather than at a micro-level from the exact stack memory consumption at a location in code.

查看更多
forever°为你锁心
6楼-- · 2019-04-05 11:24

As far as I am aware, the stack limit in Java is quite abstract and not intended for measuring. In fact, I suspect that the stack size would vary from machine to machine, based on several factors such as memory.

I've never gotten a program to throw a stack overflow exception except for infinite loops / recursion. I'm scratching my head trying to figure out how it would even be possible to throw a stack overflow exception without an infinite loop. If your program is calling that many methods, then it is likely creating objects simultaneously, and you are much more likely to receive an OutOfMemory error than a stack overflow exception without infinite loop.

In fact, what the heck would be the point of a stack limit that could limit your ability to function properly? Java has memory limits to take care of you going overboard with resources. The purpose of stack overflow is to catch loops/recursion that have run amok and need to be caught.

The point I'm trying to make is: if stack overflow exceptions plague your unit testing, you ought to check those loops/recursive functions for some out of control behavior. The call stack is very, very long and I doubt you've reached it naturally.

查看更多
登录 后发表回答