자바의 정적 할당-힙, 스택 및 영구 생성


117

나는 최근에 자바의 메모리 할당 체계에 대해 많이 읽고 있으며, 다양한 소스에서 읽고있는 동안 많은 의구심이있었습니다. 나는 내 개념을 모았고 모든 요점을 검토하고 그것에 대해 논평을 요청합니다. 메모리 할당이 JVM 특정이라는 것을 알게 되었기 때문에 내 질문은 Sun에 특정한 것이라고 미리 말해야합니다.

  1. 클래스 (클래스 로더에 의해로드 됨)는 힙의 특수 영역으로 이동합니다. 영구 생성
  2. 클래스 이름, 클래스와 연관된 오브젝트 배열, JVM에서 사용하는 내부 오브젝트 (예 : java / lang / Object) 및 최적화 정보와 같은 클래스와 관련된 모든 정보는 영구 생성 영역으로 들어갑니다.
  3. 모든 정적 멤버 변수는 영구 생성 영역에 다시 유지됩니다.
  4. 개체가 다른 힙으로 이동 : 젊은 세대
  5. 클래스 당 각 메서드의 복사본은 정적이든 비 정적이든 하나만 있습니다. 해당 사본은 영구 생성 영역에 저장됩니다. 비 정적 메서드의 경우 모든 매개 변수와 지역 변수가 스택으로 이동합니다. 해당 메서드가 구체적으로 호출 될 때마다 이와 관련된 새 스택 프레임이 생성됩니다. 정적 메서드의 지역 변수가 어디에 저장되어 있는지 잘 모르겠습니다. 영구 세대의 더미에 있습니까? 또는 참조 만 영구 생성 영역에 저장되고 실제 사본은 다른 곳에 있습니다 (어디?)
  6. 메서드의 반환 유형이 어디에 저장되는지 확실하지 않습니다.
  7. 객체 (젊은 세대)가 정적 멤버 (영구적 세대)를 사용해야하는 경우 정적 멤버에 대한 참조가 주어지고 && 메서드의 반환 유형 등을 저장할 수있는 충분한 메모리 공간이 제공됩니다.

이것을 통해 주셔서 감사합니다!

답변:


152

첫째, 직접적인 지식을 통해 이러한 답변을 확인할 수있는 사람이 거의 없음을 지금까지 분명히 알고 있어야합니다. 최근 HotSpot JVM에 대해 작업하거나 실제로 알아야하는 깊이까지 연구 한 사람은 거의 없습니다. 여기에있는 대부분의 사람들 (나 자신 포함)은 다른 곳에서 쓴 것을 본 것 또는 추론 한 내용을 기반으로 답변합니다. 일반적으로 여기 또는 다양한 기사 및 웹 페이지에 쓰여진 내용은 결정적이지 않을 수도있는 다른 소스를 기반으로합니다. 종종 그것은 단순화되거나, 부정확하거나, 명백하게 잘못되었습니다.

답변을 확실하게 확인하려면 OpenJDK 소스 코드를 다운로드 하고 소스 코드를 읽고 이해 하여 직접 조사해야합니다 . SO에 대해 질문하거나 임의의 웹 기사를 통해 트롤링하는 것은 건전한 학술 연구 기술이 아닙니다.

라고 한 ...

... 제 질문은 Sun과 관련이 있습니다.

이 질문을 받았을 때 Sun Microsystems는 더 이상 존재하지 않았습니다. 따라서 질문은 Oracle에만 해당됩니다. AFAIK, 모든 현재 (비 연구) 타사 JVM 구현은 OpenJDK 릴리스의 직접 포트이거나 다른 Sun / Oracle 릴리스의 후손입니다.

아래 답변은 Oracle Hotspot 및 OpenJDK 릴리스에 적용되며 GraalVM을 비롯한 대부분의 다른 릴리스에도 적용됩니다.

1) 클래스 (클래스 로더에 의해로드 됨)는 힙의 특수 영역 : 영구 생성으로 이동합니다.

Java 8 이전에는 그렇습니다.

Java 8부터 PermGen 공간이 Metaspace로 대체되었습니다. 로드되고 JIT로 컴파일 된 클래스가 이제 여기로 이동합니다. PermGen은 더 이상 존재하지 않습니다.

2) 클래스 이름, 클래스와 관련된 Object 배열, JVM에서 사용하는 내부 객체 (예 : java / lang / Object) 및 최적화 정보와 같은 클래스와 관련된 모든 정보가 영구 생성 영역으로 들어갑니다.

다소간 그렇습니다. 나는 당신이 그런 것들 중 일부가 무엇을 의미하는지 잘 모르겠습니다. "JVM에서 사용하는 내부 개체 (예 : java / lang / Object)"는 JVM 내부 클래스 설명자를 의미한다고 생각합니다.

3) 모든 정적 멤버 변수는 영구 생성 영역에 다시 유지됩니다.

변수 자체가 그렇습니다. 이러한 변수 (모든 Java 변수와 마찬가지로)는 기본 값 또는 객체 참조를 보유합니다. 그러나 정적 멤버 변수가 permgen 힙에 할당 된 프레임에있는 동안 해당 변수가 참조하는 개체 / 배열은 모든 힙에 할당 될 수 있습니다 .

4) 객체가 다른 힙으로 이동 : 젊은 세대

반드시 그런 것은 아닙니다. 큰 개체 종신 세대에 직접 할당 될 수 있습니다.

5) 클래스마다 각 메서드의 복사본이 하나만 있습니다 (정적 또는 비 정적 메서드). 해당 사본은 영구 생성 영역에 저장됩니다.

메소드의 코드를 참조한다고 가정하면 AFAIK가 그렇습니다. 그래도 조금 더 복잡 할 수 있습니다. 예를 들어 해당 코드는 JVM 수명 동안 다른 시간에 바이트 코드 및 / 또는 원시 코드 형식으로 존재할 수 있습니다.

... 비 정적 메서드의 경우 모든 매개 변수와 지역 변수가 스택으로 이동합니다. 해당 메서드의 구체적인 호출이있을 때마다 이와 관련된 새 스택 프레임이 생성됩니다.

예.

... 정적 메서드의 지역 변수가 어디에 저장되어 있는지 잘 모르겠습니다. 영구 세대의 더미에 있습니까? 또는 참조 만 영구 생성 영역에 저장되고 실제 사본은 다른 곳에 있습니다 (어디?)

아니요. 비 정적 메서드의 지역 변수와 마찬가지로 스택에 저장됩니다.

6) 메소드의 반환 유형이 어디에 저장되는지 확실하지 않습니다.

무효가 아닌 메서드 호출에 의해 반환 된 을 의미하는 경우 스택 또는 시스템 레지스터에 반환됩니다. 스택에 반환되는 경우 반환 유형에 따라 한두 단어가 필요합니다.

7) 객체 (젊은 세대)가 정적 멤버 (영구적 세대)를 사용해야하는 경우 정적 멤버에 대한 참조가 주어지고 && 메서드의 반환 유형을 저장할 충분한 메모리 공간이 제공됩니다. .

이는 부정확합니다 (또는 적어도 자신을 명확하게 표현하지 않음).

일부 메서드가 정적 멤버 변수에 액세스하는 경우 가져 오는 것은 기본 값 또는 개체 참조 입니다. 이것은 (기존) 지역 변수 또는 매개 변수에 할당되거나, (기존) 정적 또는 비 정적 멤버에 할당되거나, 이전에 할당 된 배열의 (기존) 요소에 할당되거나, 단순히 사용 및 폐기 될 수 있습니다.

  • 어떤 경우 에도 참조 또는 기본 값을 보유하기 위해 스토리지를 할당 할 필요가 없습니다.

  • 일반적으로 객체 또는 배열 참조를 저장하는 데 필요한 메모리 한 단어 만 있으면되고, 기본 값은 일반적으로 하드웨어 아키텍처에 따라 한두 단어를 차지합니다.

  • 어떤 경우에도 메서드에 의해 반환 된 일부 객체 / 배열을 보유하기 위해 호출자가 공간을 할당 할 필요가 없습니다. Java에서 객체와 배열은 항상 값별 전달 의미를 사용하여 반환되지만 반환되는 값은 객체 또는 배열 참조입니다.


자세한 내용은 다음 리소스를 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.