dev*_*ium 15 java stack profiling jvm
我正在尝试确定每个方法在运行时消耗的堆栈内存量.为了完成这项任务,我设计了这个简单的程序,它只会强制执行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();
}
}
Run Code Online (Sandbox Code Playgroud)
打印一个整数,告诉我m()调用了多少次.我手动将JVM的堆栈大小(-XssVM参数)设置为不同的值(128k,256k,384k),获得以下值:
stack i delta
128 1102
256 2723 1621
384 4367 1644
Run Code Online (Sandbox Code Playgroud)
delta由我计算,它是最后一行i和当前行之间的值.正如所料,它是固定的.这就是问题所在.据我所知,堆栈大小内存增量为128k,这样每次调用就会产生80byte内存(这看起来有点夸张).
查看m()BytecodeViewer,我们得到堆栈的最大深度为2.我们知道这是一个静态方法,并且没有this参数传递,并且m()没有参数.我们还必须考虑返回地址指针.因此每个方法调用应该使用3*8 = 24个字节(我假设每个变量有8个字节,当然可能完全关闭.是吗?).即使它比这更多,让我们说48字节,我们仍然远离80字节的价值.
我认为它可能与内存对齐有关,但事实是,在这种情况下,我们会有大约64或128字节的值,我会说.
我在64位Windows7操作系统下运行64位JVM.
我做了几个假设,其中一些可能完全没有.就是这样,我全都听见了.
在任何人开始问我为什么要这样做之前 我必须坦率地说..
这个问题可能超出了我的理解范围,也许你正在更深层次地谈论这个问题,但无论如何我都会给出我的答案。
首先,你指的是什么return address pointer?当一个方法完成时,返回方法将从堆栈帧中弹出。因此,执行方法 Frame 中不存储返回地址。
Frame 方法存储局部变量。由于它是静态的且无参数,所以正如您所说,这些应该是空的,并且操作堆栈和局部变量的大小在编译时是固定的,每个单元都是 32 位宽。但除此之外,该方法还必须具有对其所属类的常量池的引用。
另外,JVM 规范指定了may be extended with additional implementation-specific information, such as debugging information.可以解释剩余字节的方法框架,具体取决于编译器。
全部源自JVM 框架规范。
更新
搜索 OpenJDK 源代码揭示了这一点,它似乎是在方法调用时传递给 Frames 的结构。很好地洞察了其中的期望:
/* 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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
340 次 |
| 最近记录: |