Java에서의 정적 할당 - 힙, 스택 및 영구 생성
최근 자바 메모리 할당 방식에 대해 많이 읽었는데, 여러 출처에서 읽으면서 여러 가지 의문점이 있었습니다.저는 저의 컨셉을 취합했고, 모든 포인트를 검토하고 코멘트를 부탁드리고 싶습니다.메모리 할당은 JVM에 따라 다르므로 Sun에 따라 다르다고 미리 말해야 합니다.
- 클래스(클래스로더에 의해 로드됨)는 히프의 특수 영역인 Permanent Generation(영구 생성)으로 이동합니다.
- 클래스의 이름, 클래스에 관련된 오브젝트 배열, JVM에서 사용되는 내부 오브젝트(java/lang/Object 등) 및 최적화 정보와 같은 모든 정보는 Permanent Generation 영역에 들어갑니다.
- 모든 스태틱멤버 변수는 [Permanent Generation]영역에 다시 저장됩니다.
- 개체가 다른 힙으로 이동함: Young generation
- 각 메서드의 복사본은 클래스별로 static 메서드 또는 non-static 메서드 중 하나만 있습니다.그 복사본은 영구 세대 영역에 놓입니다.비정적 메서드의 경우 모든 파라미터와 로컬 변수가 스택으로 이동합니다.이 메서드의 구체적인 호출이 있을 때마다 관련된 새로운 스택프레임이 생성됩니다.정적 메서드의 로컬 변수가 어디에 저장되어 있는지 알 수 없습니다.그들은 영구 세대의 산더미 위에 있나요?또는 레퍼런스만 Permanent Generation 영역에 저장되어 실제 복사본은 다른 곳에 있습니다(어디서).
- 메서드의 반환 유형은 어디에 저장되는지 알 수 없습니다.
- (젊은 세대의) 오브젝트가 (영구 세대의) 스태틱멤버를 사용할 필요가 있는 경우 스태틱멤버를 참조하고 메서드의 반환 타입 등을 저장하기에 충분한 메모리 공간이 주어집니다.
잘부탁드립니다!
첫째, 지금까지 이러한 답변을 직접 알고 확인할 수 있는 사람은 거의 없다는 것을 분명히 해야 합니다.최근 HotSpot JVM에 대해 작업하거나 실제로 알아야 할 깊이까지 연구한 사람은 거의 없습니다.여기 있는 대부분의 사람들(나 자신도 포함)은 그들이 다른 곳에서 본 것 또는 그들이 추론한 것에 근거해 대답하고 있다.일반적으로 여기, 또는 다양한 기사나 웹페이지에 기재되어 있는 내용은 확정적이지 않을 수도 있는 다른 출처에 근거하고 있습니다.단순화되고 부정확하거나 완전히 잘못된 경우가 많습니다.
답변을 확실하게 확인하려면 OpenJDK 소스 코드를 다운로드하고 소스 코드를 읽고 이해함으로써 직접 조사해야 합니다.SO에 대해 질문하거나 임의의 웹 기사를 탐색하는 것은 건전한 학술 연구 기술이 아닙니다.
그렇다고는 해도...
제 질문은 태양에 관한 것입니다.
이 질문이 제기되었을 때 Sun Microsystems는 존재하지 않게 되었습니다.따라서 이 질문은 Oracle에 고유했습니다.AFAIK, 현재 (조사 대상이 아닌) 서드파티제의 모든 JVM 구현은 OpenJDK 릴리스의 직접 포트이거나 다른 Sun/Oracle 릴리스의 하위 포트입니다.
다음 답변은 Oracle Hotspot 및 OpenJDK 릴리즈에 적용되며, 다른 대부분의 릴리스에도 적용될 수 있습니다.GraalVM을 포함합니다.
1) 클래스(클래스로더에 의해 로드됨)는 히프의 특수 영역인 Permanent Generation에 들어갑니다.
Java 8 이전 버전에서는 그렇습니다.
Java 8에서 PermGen 공간은 Metaspace로 대체되었습니다.로드된 클래스와 JIT 컴파일된 클래스가 표시됩니다.PermGen은 더 이상 존재하지 않습니다.
2) 클래스의 이름, 클래스에 관련된 오브젝트 배열, JVM에서 사용되는 내부 오브젝트(java/lang/Object 등), 최적화 정보와 관련된 모든 정보가 Permanent Generation 영역에 들어갑니다.
어느 정도, 네.그 중 몇 가지는 무슨 뜻인지 잘 모르겠어요.JVM이 사용하는 내부 객체(java/lang/Object 등)는 JVM 내부 클래스 기술자를 의미한다고 생각합니다.
3) 모든 스태틱멤버 변수는 [Permanent Generation]영역에 다시 저장됩니다.
변수 자체는 그렇다.이러한 변수(모든 Java 변수와 마찬가지로)는 원시 값 또는 개체 참조를 유지합니다.단, 스태틱멤버 변수가 permgen 힙에 할당되어 있는 프레임에 있는 동안 이들 변수에 의해 참조되는 오브젝트 또는 어레이는 임의의 힙에 할당할 수 있습니다.
4) 객체가 다른 힙으로 이동: Young generation
꼭 그렇다고 할 수는 없죠.큰 오브젝트는 테넌트 세대에 직접 할당할 수 있습니다.
5) static 또는 non-static 방식으로 클래스당 각 메서드의 복사본은 1개뿐입니다.그 복사본은 영구 세대 영역에 놓입니다.
메서드의 코드를 참조하고 있다고 가정하면, AFAIK는 네.하지만 조금 더 복잡할 수도 있습니다.예를 들어 이 코드는 JVM의 수명 동안 서로 다른 시기에 바이트 코드 및/또는 네이티브 코드 형식으로 존재할 수 있습니다.
...비정적 메서드의 경우 모든 파라미터와 로컬 변수가 스택으로 이동합니다.이 메서드의 구체적인 호출이 있을 때마다 관련된 새로운 스택프레임이 생성됩니다.
네.
... 스태틱 메서드의 로컬 변수가 어디에 저장되어 있는지 알 수 없습니다.그들은 영구 세대의 산더미 위에 있나요?또는 레퍼런스만 Permanent Generation 영역에 저장되어 실제 복사본은 다른 곳에 있습니다(어디서).
아니요. 비정적 방식의 로컬 변수처럼 스택에 저장됩니다.
6) 메서드의 반환 타입은 어디에 저장되어 있는지도 잘 모르겠습니다.
(비포이드) 메서드콜에 의해 반환된 값을 의미하는 경우 스택 또는 머신레지스터로 반환됩니다.스택으로 반환되는 경우 반환 유형에 따라 1, 2단어가 소요됩니다.
(젊은 세대) 오브젝트가 (영구 세대) 스태틱 부재를 사용할 필요가 있는 경우 스태틱 부재를 참조하고 메서드의 반환 타입 등을 저장하기에 충분한 메모리 공간을 부여한다.
그것은 부정확하다(적어도 당신은 자신을 명확하게 표현하지 못하고 있다).
어떤 메서드가 정적 멤버 변수에 액세스할 경우 원시 값 또는 개체 참조 중 하나를 얻을 수 있습니다.이는 (기존) 로컬 변수 또는 파라미터에 할당하거나 (기존) 스태틱 또는 비 스태틱멤버에 할당하거나 이전에 할당한 배열의 (기존) 요소에 할당하거나 단순히 사용하여 폐기할 수 있습니다.
어떤 경우에도 참조 값이나 기본 값을 유지하기 위해 새 스토리지를 할당할 필요가 없습니다.
일반적으로 메모리 한 단어만 있으면 객체 또는 어레이 참조를 저장할 수 있으며, 하드웨어 아키텍처에 따라서는 보통 원시 값이 한두 단어를 차지합니다.
메서드에 의해 반환된 객체/배열을 유지하기 위해 호출자가 공간을 할당할 필요는 없습니다.Java에서는 개체와 배열은 항상 값별 시멘틱스를 사용하여 반환되지만 반환되는 값은 개체 또는 배열 참조입니다.
상세한 것에 대하여는, 다음의 자원을 참조해 주세요.
- 클래스 메타데이터: 사용자 가이드
- PermGen과 Metaspace의 차이점은 무엇입니까?
- Java 8: PermGen에서 메타스페이스로
- G1 가비지 콜렉터, 영구 생성 및 메타스페이스에 대해서
언급URL : https://stackoverflow.com/questions/3849634/static-allocation-in-java-heap-stack-and-permanent-generation
'source' 카테고리의 다른 글
여러 키를 사용하여 맵을 구현하는 방법 (0) | 2022.09.03 |
---|---|
소품 및 데이터 중복을 방지하려면 어떻게 해야 합니까? (0) | 2022.09.03 |
python 확장 - swig 또는 Cython이 아닌 swig로 확장 (0) | 2022.09.03 |
javascript에서 . (dot)를 숫자와 연결하는 방법 (0) | 2022.09.01 |
Vue 구성 요소를 테스트할 때 측면 플러그인을 시뮬레이션하는 방법 (0) | 2022.09.01 |