Java의 정적 할당-힙, 스택 및 영구 생성
최근에 자바에서 메모리 할당 체계에 대해 많은 것을 읽었으며 다양한 소스에서 읽었을 때 많은 의문이있었습니다. 나는 내 개념을 모았으며 모든 요점을 살펴보고 그것에 대해 의견을 제시 할 것을 요청했습니다. 메모리 할당이 JVM마다 다르다는 것을 알게되었으므로 미리 질문해야합니다. 제 질문은 Sun에만 해당됩니다.
- 클래스 (클래스 로더가로드 한) 클래스는 힙의 특수 영역으로 이동합니다.
- 클래스 이름, 클래스와 연관된 오브젝트 배열, JVM에서 사용하는 내부 오브젝트 (예 : java / lang / Object) 및 최적화 정보와 같은 클래스와 관련된 모든 정보는 영구 생성 영역으로 이동합니다.
- 모든 정적 멤버 변수는 영구 생성 영역에 다시 유지됩니다.
- 객체는 다른 힙에 간다 : 젊은 세대
- 클래스마다 각 메소드의 사본이 하나만 있습니다 (정적 또는 비 정적 메소드). 이 사본은 영구 생성 영역에 있습니다. 비 정적 메서드의 경우 모든 매개 변수와 로컬 변수가 스택으로 이동합니다. 해당 메서드가 구체적으로 호출 될 때마다 새로운 스택 프레임이 연결됩니다. 정적 메소드의 로컬 변수가 어디에 저장되어 있는지 잘 모르겠습니다. 그들은 영원한 세대의 더미에 있습니까? 또는 참조 만 영구 생성 영역에 저장되고 실제 사본은 다른 곳에 있습니다 (어디?).
- 또한 메소드의 리턴 유형이 어디에 저장되는지 확실하지 않습니다.
- (젊은 세대의) 객체가 정적 멤버 (영구적 세대의)를 사용해야하는 경우 정적 멤버에 대한 참조가 제공되며 & & 메소드의 반환 유형 등을 저장할 수있는 충분한 메모리 공간이 제공됩니다.
이것을 통해 주셔서 감사합니다!
먼저, 지금까지 분명한 바와 같이 직접 지식을 통해 이러한 답변을 확인할 수있는 사람은 거의 없습니다. 최근 핫스팟 JVM에서 작업하거나 실제로 알아야 할 깊이까지 연구 한 사람은 거의 없습니다. 여기에있는 대부분의 사람들 (자신 포함)은 다른 곳에서 작성한 것으로 보거나 추측 한 것을 기반으로 응답하고 있습니다. 일반적으로 여기 또는 다양한 기사와 웹 페이지에 기록 된 내용은 결정적이거나 결정적이지 않은 다른 출처를 기반으로합니다. 종종 그것은 단순화되거나 부정확하거나 명백한 잘못입니다.
답을 확실하게 확인하려면 OpenJDK 소스 코드를 다운로드 하고 소스 코드를 읽고 이해 하여 직접 조사해야합니다 . SO에 대한 질문이나 임의의 웹 기사를 통한 트롤링은 건전한 학술 연구 기술이 아닙니다.
라고 한 ...
1) 클래스 (클래스 로더에 의해로드 된)는 힙의 특수 영역 인 영구 생성에 들어갑니다.
AFAIK입니다. ( 업데이트 : 아래 참조)
2) 클래스 이름, 클래스와 관련된 객체 배열, JVM에서 사용하는 내부 객체 (java / lang / Object 등) 및 최적화 정보와 같은 클래스와 관련된 모든 정보는 영구 생성 영역으로 들어갑니다.
더 많거나 적습니다. 나는 당신이 그 것들 중 무엇을 의미하는지 잘 모르겠습니다. "java / lang / Object와 같은 JVM에서 사용하는 내부 객체"는 JVM 내부 클래스 설명자를 의미한다고 생각합니다.
3) 모든 정적 멤버 변수는 영구 생성 영역에 다시 유지됩니다.
변수 자체는 그렇습니다. 이러한 변수 (모든 Java 변수와 마찬가지로)는 기본 값 또는 객체 참조를 보유합니다. 그러나 정적 멤버 변수가 permgen 힙에 할당 된 프레임에있는 동안 해당 변수가 참조하는 객체 / 배열은 임의의 힙에 할당 될 수 있습니다 .
4) 객체가 다른 힙으로 이동 : 젊은 세대
반드시 그런 것은 아닙니다. 큰 개체 는 tenured 세대에 직접 할당 될 수 있습니다.
5) 클래스마다 각 메소드의 사본이 하나만 있습니다 (정적 또는 비 정적 메소드). 이 사본은 영구 생성 영역에 있습니다.
메소드의 코드를 참조한다고 가정하면 AFAIK는 예입니다. 그래도 조금 더 복잡 할 수 있습니다. 예를 들어, 해당 코드는 JVM 수명 동안 다른 시간에 바이트 코드 및 / 또는 기본 코드 형태로 존재할 수 있습니다.
... 비 정적 메서드의 경우 모든 매개 변수와 로컬 변수가 스택으로 이동합니다. 해당 메서드를 구체적으로 호출 할 때마다 새로운 스택 프레임이 연결됩니다.
예.
... 정적 메소드의 로컬 변수가 어디에 저장되어 있는지 잘 모르겠습니다. 그들은 영원한 세대의 더미에 있습니까? 또는 참조 만 영구 생성 영역에 저장되고 실제 사본은 다른 곳에 있습니다 (어디?).
아니요. 비 정적 메서드의 로컬 변수와 마찬가지로 스택에 저장됩니다.
6) 메소드의 리턴 유형이 어디에 저장되는지 잘 모르겠습니다.
무효가 아닌 메소드 호출에 의해 리턴 된 값 을 의미하는 경우 , 스택 또는 시스템 레지스터에 리턴됩니다. 스택에 반환되면 반환 유형에 따라 1-2 단어가 필요합니다.
7) (젊은 세대의) 객체가 정적 멤버 (영구적 세대)를 사용해야하는 경우 정적 멤버에 대한 참조가 제공되며 & 메소드의 반환 유형을 저장할 수있는 충분한 메모리 공간이 제공됩니다. .
그것은 정확하지 않습니다 (또는 적어도 자신을 명확하게 표현하지는 않습니다).
일부 메소드가 정적 멤버 변수에 액세스하는 경우 기본 값 또는 오브젝트 참조 입니다. 이것은 (기존) 로컬 변수 또는 매개 변수에 할당되거나, (기존) 정적 또는 비 정적 멤버에 할당되거나, 이전에 할당 된 배열의 (기존) 요소에 할당되거나, 단순히 사용 및 폐기 될 수 있습니다.
어떠한 경우 에도 참조 또는 기본 값을 보유하기 위해 새 스토리지를 할당 할 필요가 없습니다.
일반적으로 객체 또는 배열 참조를 저장하는 데 필요한 한 단어의 메모리 만 있으면 기본 값은 일반적으로 하드웨어 아키텍처에 따라 하나 또는 두 개의 단어를 차지합니다.
어떤 경우에도 메소드가 리턴 한 오브젝트 / 배열을 보유하기 위해 호출자가 공간을 할당 할 필요는 없습니다. Java에서 객체 및 배열은 항상 값별 의미 체계를 사용하여 반환되지만 반환되는 값은 객체 또는 배열 참조입니다.
최신 정보
Java 8부터는 PermGen 공간이 메타 스페이스로 대체되었습니다. 자세한 내용은 다음 자료를 참조하십시오.
'programing tip' 카테고리의 다른 글
"스텁"이란 무엇입니까? (0) | 2020.08.02 |
---|---|
(A + B + C) ≠ (A + C + B) 및 컴파일러 재정렬 (0) | 2020.08.02 |
KeyValuePair VS DictionaryEntry (0) | 2020.08.02 |
JSON.parse 예기치 않은 문자 오류 (0) | 2020.07.30 |
예외 또는 오류 코드에 대한 규칙 (0) | 2020.07.30 |