각 메소드가 실행할 때 소비하는 스택 메모리의 양을 확인하려고합니다. 작업을 수행하려면, 나는 m()
가 호출 된 횟수를 말해 정수를 인쇄 단지 StackOverflowError
강제로이 간단한 프로그램,Java에서 메소드의 스택 메모리 사용을 추정합니다.
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();
}
}
을 고안했습니다. 나는 수동으로 다음과 같은 값을 획득, 다양한 값 (128K, 256K, 384K)에 JVM의 스택 크기 (-Xss
VM 매개 변수)를 설정 한 :
stack i delta
128 1102
256 2723 1621
384 4367 1644
델타는 나에 의해 계산하고 마지막 사이의 값입니다했다 라인의 i와 현재의 것. 예상대로 고정됩니다. 그리고 그 문제가 있습니다. 스택 크기 메모리 증가량이 128k 였으므로 호출 당 80byte 메모리 사용과 같은 결과를 낳습니다 (이는 과장된 것처럼 보입니다). 최대 m()
BytecodeViewer의에서 찾고
, 우리는 우리는이 정적 방법을 알고 2의 스택의 최대 깊이를 얻을 거기에는 this
매개 변수 전달 없다, 그 m()
이 인수가 없다. 또한 리턴 주소 포인터를 고려해야합니다. 그래서 메서드 호출 당 3 * 8 = 24 바이트를 사용해야합니다 (변수 당 8 바이트라고 가정하고 있습니다. 물론 그럴 수 있습니까?). 그것이 그보다 조금더라도, 48 바이트라고 가정 해 봅시다. 우리는 여전히 80 바이트 값에서 멀리 떨어져 있습니다.
메모리 정렬과 관련이있을 수 있다고 생각했지만, 그 경우 약 64 또는 128 바이트의 값을 가질 수 있습니다.
저는 64 비트 Windows7 OS에서 64 비트 JVM을 실행하고 있습니다.
몇 가지 가정을했는데 그 중 일부는 완전히 해제되었을 수 있습니다. 그 경우, 나는 모든 귀입니다.
사람이 당신이 믿지 않는 경우에도 저장되어 다른 컨텍스트 정보를 당신은 스택에 명령 포인터 (8 바이트)를 포함하기 위해 필요한이 I must be frank..
그건 통찰력있는 정보였습니다. 각 메서드 호출이 80 바이트를 차지하는 이유에 대해 이론화 해 주시겠습니까? –
프레임 구조 내에서 내 자신의 JVM 구현이 보유하고있는 정보를 말할 수 있습니까? – Jivings
@devouredelysium OpenJDK 소스로 내 대답을 업데이트했습니다. – Jivings