Inferring a method#39;s stack memory use in Java(在 Java 中推断方法的堆栈内存使用情况)
问题描述
I'm trying to determine how much stack memory each method consumes when running. To do the task, I've devised this simple program that will just force a StackOverflowError
,
public class Main {
private static int i = 0;
public static void main(String[] args) {
try {
m();
} catch (StackOverflowError e) {
System.err.println(i);
}
}
private static void m() {
++i;
m();
}
}
printing an integer telling me how many times m()
was called. I've manually set the JVM's stack size(-Xss
VM parameter) to varying values (128k, 256k, 384k), obtaining the following values:
stack i delta
128 1102
256 2723 1621
384 4367 1644
delta was calculated by me, and it's the value between the last line's i and the current one's. As expected it is fixed. And there lies the problem. As I know the stack size memory increment was by 128k, that yields something like a 80byte memory use per call (which seems exaggerated).
Looking up m()
in BytecodeViewer's, we get a stack's max depth of 2. We know this is a static method and that there's no this
parameter passing, and that m()
has no arguments. We must also take into consideration the return address pointer. So there should be something like 3 * 8 = 24 bytes used per method call (I'm assuming 8 bytes per variable, which of course may be totally off. Is it?). Even if it's a bit more than that, let's say 48bytes, we're still far away from the 80bytes value.
I thought it could have something to do with memory alignment, but truth is that in that case we'd have a value of roughly 64 or 128 bytes, I'd say.
I'm running a 64bit JVM under a 64bit Windows7 OS.
I've made several assumptions, some of which may be totally off. Being that the case, I'm all ears.
Before anyone starts asking why I'm doing this I must be frank..
This question may be way over my head, perhaps you are talking about this on a deeper level, but I'll throw my answer out there anyway.
Firstly, what do you refer to by return address pointer
? When a method is finished the return method is popped from the stack frame. So no return address is stored within the executing method Frame.
The method Frame stores local variables. Since it's static, and parameterless, these should be empty as you say, and the sizes of the op stack and locals are fixed at compile time, with each unit in each being 32bits wide. But as well as this the method also must have a reference to the constant pool of the class to which it belongs.
In additional the JVM spec specifies that method frames may be extended with additional implementation-specific information, such as debugging information.
Which could explain the remaining bytes, depending on the compiler.
All sourced from the JVM Specification on Frames.
UPDATE
Scouring the OpenJDK source reveals this, which appears to be the struct that is passed to Frames on method invocation. Gives a pretty good insight on what to expect within:
/* Invoke types */
#define INVOKE_CONSTRUCTOR 1
#define INVOKE_STATIC 2
#define INVOKE_INSTANCE 3
typedef struct InvokeRequest {
jboolean pending; /* Is an invoke requested? */
jboolean started; /* Is an invoke happening? */
jboolean available; /* Is the thread in an invokable state? */
jboolean detached; /* Has the requesting debugger detached? */
jint id;
/* Input */
jbyte invokeType;
jbyte options;
jclass clazz;
jmethodID method;
jobject instance; /* for INVOKE_INSTANCE only */
jvalue *arguments;
jint argumentCount;
char *methodSignature;
/* Output */
jvalue returnValue; /* if no exception, for all but INVOKE_CONSTRUCTOR */
jobject exception; /* NULL if no exception was thrown */
} InvokeRequest;
Source
这篇关于在 Java 中推断方法的堆栈内存使用情况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在 Java 中推断方法的堆栈内存使用情况
基础教程推荐
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 在螺旋中写一个字符串 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01