Я пытаюсь определить, сколько стековой памяти использует каждый метод при запуске. Чтобы выполнить задачу, я разработал эту простую программу, которая просто вызовет 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();
}
}
печать целого числа, говорящего мне, сколько раз m()
был вызван. Я вручную установил размер стека JVM (-Xss
параметр VM) на разные значения (128k, 256k, 384k), получив следующие значения:
stack i delta
128 1102
256 2723 1621
384 4367 1644
дельта была рассчитана мной, и это значение между последней строкой i и текущей. Как и ожидалось, это исправлено. И здесь кроется проблема. Как я знаю, приращение памяти в размере стека составило 128 КБ, что дает примерно 80-байтовое использование памяти на вызов (что кажется преувеличенным).
Глядя на m()
в BytecodeViewer, мы получаем максимальную глубину стека, равную 2. Мы знаем, что это статический метод, и здесь отсутствует передача параметров this
, а у m()
нет аргументов. Мы также должны принять во внимание указатель обратного адреса. Таким образом, должно быть что-то вроде 3 * 8 = 24 байта, используемых на вызов метода (я предполагаю, что 8 байтов на переменную, что, конечно, может быть полностью отключено. Это так?). Даже если это немного больше, скажем, 48 байт, мы все еще далеки от значения 80 байт.
Я думал, что это может иметь какое-то отношение к выравниванию памяти, но правда в том, что в этом случае у нас будет примерно 64 или 128 байтов, я бы сказал.
Я использую 64-битную JVM под 64-битной ОС Windows7.
Я сделал несколько предположений, некоторые из которых могут быть полностью неверными. В таком случае я весь слух.
Прежде чем кто-то начнет спрашивать, почему я это делаю Я должен быть откровенным ..