자바 대상 구조 대상 헤드 Markword

개술
대상 인 스 턴 스 는 대상 헤드,인 스 턴 스 데이터 로 구성 되 는데 그 중에서 대상 헤드 는 markword 와 유형 지침 을 포함 하고 배열 이 라면 배열 길이 도 포함한다.
|유형|32 비트 JVM|64 비트 JVM|
| ------ ---- | ------------| --------- |
| markword | 32bit | 64bit |
|유형 포인터|32bit|64bit,포인터 압축 시 32bit|
|배열 길이|32bit|32bit|

header.png

compressed_header.png
볼 수 있다
포인터 압축 을 열 때 markword 는 8bytes 를 차지 하고 유형 지침 은 8bytes 를 차지 하 며 모두 16bytes 를 차지한다.
포인터 압축 이 열 리 지 않 았 을 때 markword 는 8bytes 를 차지 하고 유형 지침 은 4bytes 를 차지 하지만 자바 메모리 주 소 는 8bytes 에 따라 정렬 되 기 때문에 길 이 는 8 의 배수 여야 하기 때문에 12bytes 에서 16bytes 로 보 완 됩 니 다.
배열 의 길 이 는 4bytes 이 고 똑 같이 정렬 하여 8bytes 까지 보충 합 니 다.
또한 위의 캡 처 를 통 해 알 수 있 듯 이 포인 터 를 열 어 압축 한 후 대상 유형 포인 터 는 0xf800c 005 이지 만 실제 유형 포인 터 는 0x7c 0060028 이다.그러면 지침 은 어떻게 압축 됩 니까?
실제로 자바 주 소 는 반드시 8 의 배수 이기 때문에 0xf800c 005*8 을 실제 지침 0x7c 0060028 을 얻 을 수 있 습 니 다.지침 압축 에 관 한 더 많은 지식공식 문 서 를 참고 하 다.
markword 구조
markword 의 구조,markOop.hpp 파일 에 정의:

 32 bits:
 --------
 hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
 JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
 size:32 ------------------------------------------>| (CMS free block)
 PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)

 64 bits:
 --------
 unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
 JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
 PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
 size:64 ----------------------------------------------------->| (CMS free block)

 unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)
 JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)
 narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
 unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
 [ptr    | 00] locked    ptr points to real header on stack
 [header  | 0 | 01] unlocked   regular object header
 [ptr    | 10] monitor   inflated lock (header is wapped out)
 [ptr    | 11] marked    used by markSweep to mark an object
현재 64 비트 JVM 을 기본적으로 사용 하고 있 기 때문에 32 비트 의 구조 에 대해 자세히 설명 하지 않 습 니 다.
편향 잠 금 표식 위치
자물쇠 표지 비트
잠 금 상태
저장 내용
0
01
잠 겨 있 지 않 음
hash code(31),나이(4)
1
01
편향 자물쇠
라인 ID(54),타임 스탬프(2),나이(4)
없다
00
경량급 자물쇠
창고 에 기 록 된 자물쇠 바늘(64)
없다
10
헤비급 자물쇠
모니터 의 포인터(64)
없다
11
GC 태그
비어 있 습 니 다.정 보 를 기록 할 필요 가 없습니다.
여기에 몇 가지 주의해 야 할 점 이 있 습 니 다.
대상 이 hashcode 를 다시 쓰 는 방법 이 없다 면 기본 값 은 os:random 을 호출 하여 hashcode 를 만 들 고 System.identity HashCode 를 통 해 얻 을 수 있 습 니 다.os::random 에서 hashcode 를 만 드 는 규칙 은:nextrand=(16807 seed)mod(2*31-1),따라서 31 비트 저장 소 를 사용 할 수 있 습 니 다.또한 hashcode 가 생 성 되면 JVM 은 markword 에 기록 합 니 다.
GC 나 이 는 4 비트 bit 로 저장 되 고 최대 15 입 니 다.예 를 들 어 MaxTenuringThreshold 매개 변 수 는 기본 값 이 15 입 니 다.
경량급 자물쇠,헤비급 자물쇠 에 있 을 때 기 록 된 대상 지침 은 JVM 의 설명 에 따 르 면 이때 지침 은 여전히 64 자리 이 고 최저 두 자 리 는 0 으로 가정 한다.편향 잠 금 에 있 을 때 편향 잠 금 을 얻 기 위 한 스 레 드 포인터 가 기록 되 어 있 으 며 이 포인터 도 64 비트 입 니 다.

 We assume that stack/thread pointers have the lowest two bits cleared.
ObjectMonitor* monitor() const {
 assert(has_monitor(), "check");
 // Use xor instead of &~ to provide one extra tag-bit check.
 return (ObjectMonitor*) (value() ^ monitor_value);//monitor_value=2,value     10,           0
 }
JavaThread* biased_locker() const {
 assert(has_bias_pattern(), "should not call this otherwise");
 return (JavaThread*) ((intptr_t) (mask_bits(value(), ~(biased_lock_mask_in_place | age_mask_in_place | epoch_mask_in_place))));
//~(biased_lock_mask_in_place | age_mask_in_place | epoch_mask_in_place) 11111111111111111111110010000000,       , 10    0;
 }
자바 의 메모리 주 소 는 모두 8 의 배수 이기 때문에 최저 3bit 가 0 으로 이해 할 수 있 기 때문에 경량급 과 중량급 자물쇠 의 최저 2 위 가 0 이 라 고 가정 하면 성립 된다.그런데 왜 자물쇠 의 최저 10 자리 가 0 일 까?markOOp.hpp 파일 을 보 니 다음 과 같은 말 이 있 습 니 다.

// Alignment of JavaThread pointers encoded in object header required by biased locking
 enum { biased_lock_alignment = 2 << (epoch_shift + epoch_bits)
//epoch_shift+epoch_bits=10
 };
thread.hpp 에 operator new 를 다시 불 러 왔 습 니 다:

void* operator new(size_t size) { return allocate(size, true); }

// ======= Thread ========
// Support for forcing alignment of thread objects for biased locking
void* Thread::allocate(size_t size, bool throw_excpt, MEMFLAGS flags) {
 if (UseBiasedLocking) {
 const int alignment = markOopDesc::biased_lock_alignment;//10
 size_t aligned_size = size + (alignment - sizeof(intptr_t));
 void* real_malloc_addr = throw_excpt? AllocateHeap(aligned_size, flags, CURRENT_PC)
           : os::malloc(aligned_size, flags, CURRENT_PC);
 void* aligned_addr  = (void*) align_size_up((intptr_t) real_malloc_addr, alignment);
 assert(((uintptr_t) aligned_addr + (uintptr_t) size) <=
   ((uintptr_t) real_malloc_addr + (uintptr_t) aligned_size),
   "JavaThread alignment code overflowed allocated storage");
 if (TraceBiasedLocking) {
  if (aligned_addr != real_malloc_addr)
  tty->print_cr("Aligned thread " INTPTR_FORMAT " to " INTPTR_FORMAT,
      real_malloc_addr, aligned_addr);
 }
 ((Thread*) aligned_addr)->_real_malloc_address = real_malloc_addr;
 return aligned_addr;
 } else {
 return throw_excpt? AllocateHeap(size, flags, CURRENT_PC)
      : os::malloc(size, flags, CURRENT_PC);
 }
}
오프셋 잠 금 이 열 리 면 스 레 드 를 만 들 때 스 레 드 주 소 를 정렬 하여 10 비트 가 0 이 되도록 합 니 다.
인 스 턴 스 데이터
인 스 턴 스 데이터 에는 주로 대상 의 각종 구성원 변 수 를 포함 하 는데 기본 유형 과 참조 유형 을 포함한다.static 형식의 변 수 는 자바/lang/class 에 넣 고 인 스 턴 스 데이터 에 넣 지 않 습 니 다.
인용 형식의 구성원(string 포함)에 대한 포인터;기본 유형 에 대해 내용 을 직접 저장 합 니 다.보통 기본 형식 을 함께 저장 하고 인용 형식 을 함께 저장 합 니 다.
예 를 들 어 클래스 Test 의 구성원 정 의 는 다음 과 같다.

 private static Test t1=new Test();
 private Test t2;
 private int a=5;
 private Integer b=7;
 private String c="112";
 private BigDecimal d=new BigDecimal("5");
 private long e=9l;

body.png
롱 e,int a 를 기본 형식 으로 저장 하 는 것 을 볼 수 있 습 니 다.다른 인용 형식 이 함께 저 장 됩 니 다.int 는 4bytes 를 차지 하고 8bytes 가 부족 하 며 8bytes 까지 자동 으로 보충 합 니 다.
보충 지식:자바 의 대상 물리 구조 및 대상 머리 에서 Markword 와 자물쇠 의 관계
자바 개체 헤더
자바 대상 이 더미(Heap)메모리 에 저장 되 어 있다 는 것 을 우 리 는 모두 알 고 있다.그렇다면 자바 대상 은 무엇 을 포함 하고 있 을 까?요약 하면 대상 머리,대상 체,정렬 바이트 로 나 뉜 다.
다음 그림 에서 보 듯 이:

대상 의 몇 가지 부분의 역할:
1.대상 머리 에 있 는 Mark Word(태그 글자)는 대상 의 스 레 드 잠 금 상 태 를 나타 내 는 데 사용 되 며 GC 에 맞 춰 대상 의 hashCode 를 저장 할 수 있 습 니 다.
2.Klass Word 는 방법 구역 에서 Class 정 보 를 가리 키 는 지침 으로 이 대상 이 자신 이 어떤 Class 인지 수시로 알 수 있다 는 것 을 의미한다.
3.배열 의 길이 도 64 비트(8 바이트)를 차지 하 는 공간 입 니 다.이것 은 선택 할 수 있 습 니 다.이 대상 이 배열 대상 일 때 만 이 부분 이 있 습 니 다.
4.대상 체 는 대상 의 속성 과 값 을 저장 하 는 주체 부분 으로 메모리 공간 을 차지 하 는 것 은 대상 의 속성 수량 과 유형 에 달 려 있다.
5.글 자 를 맞 추 는 것 은 메모리 의 조각 공간 을 줄 이기 위 한 것 이다(정확 한 것 은 아니다).
대상 의 전체적인 구 조 를 이해 한 다음 에 대상 머리의 세 부분 을 깊이 이해 했다.
1.Mark Word(태그 글자)

이상 은 자바 대상 이 5 가지 서로 다른 상태 에 있 을 때 Mark Word 에서 64 비트 의 표현 형식 으로 위의 각 줄 의 대표 대상 이 특정한 상태 에 있 을 때의 모습 입 니 다.그 중의 각 부분의 의 미 는 다음 과 같다.
lock:2 비트 의 잠 금 상태 표시 위 치 는 가능 한 한 적은 바 이 너 리 로 가능 한 한 많은 정 보 를 표시 하고 싶 어서 lock 표 시 를 설정 하 였 습 니 다.이 표 시 는 값 이 다 르 고 전체 Mark Word 가 표시 하 는 의미 가 다 릅 니 다.biased_lock 과 lock 이 함께 표 현 된 자물쇠 상태의 의 미 는 다음 과 같다.

biased_lock:대상 이 편향 잠 금 표 시 를 사용 할 지 여부 입 니 다.바 이 너 리 만 차지 합 니 다.1 시 에는 대상 이 편향 자 물 쇠 를 사용 하고 0 시 에는 대상 이 편향 자물쇠 가 없 음 을 나타 낸다.lock 와 biasedlock 은 대상 이 어떤 자물쇠 상태 에 있 는 지 공동으로 표시 합 니 다.
age:4 비트 자바 대상 연령.GC 에 서 는 대상 이 서 바 이 버 존 에서 한 번 복사 되면 연령 이 1 증가한다.대상 이 설 정 된 한도 값 에 이 르 면 옛날 로 올라간다.기본적으로 병렬 GC 의 연령 한도 값 은 15 이 고 병렬 GC 의 연령 한도 값 은 6 이다.age 가 4 자리 밖 에 없 기 때문에 최대 값 은 15 입 니 다.이것 이 바로-XX:MaxTenuring Threshold 옵션 의 최대 값 이 15 인 이유 입 니 다.
identity_hashcode:31 비트 의 대상 표지 hashCode 는 로드 지연 기술 을 사용 합 니 다.호출 방법 System.identity HashCode()를 계산 하고 결 과 를 대상 머리 에 기록 합 니 다.대상 이 잠 금 을 추가 한 후(편향,경량급,중량급)Markword 의 바이트 가 hashCode 를 저장 할 공간 이 충분 하지 않 기 때문에 이 값 은 파이프 모니터 로 이동 합 니 다.
thread:편향 잠 금 스 레 드 ID 를 가지 고 있 습 니 다.
epoch:자물쇠 에 치 우 친 시간 스탬프.
ptr_to_lock_record:경량급 잠 금 상태 에서 스 택 에 기 록 된 지침 을 가리 킵 니 다.
ptr_to_heavyweight_Monitor:헤비급 잠 금 상태 에서 대상 모니터 Monitor 를 가리 키 는 지침 입 니 다.

2.Klass Word(클래스 포인터)
이 부분 은 대상 의 유형 지침 을 저장 하 는 데 사 용 됩 니 다.이 지침 은 클래스 메타 데 이 터 를 가리 키 며 JVM 은 이 지침 을 통 해 대상 이 어떤 종류의 인 스 턴 스 인지 확인 합 니 다.이 포인터 의 비트 길 이 는 JVM 의 한 글자 크기 인 32 비트 JVM 32 비트,64 비트 JVM 64 비트 입 니 다.
응용 대상 이 너무 많 으 면 64 비트 의 지침 을 사용 하면 대량의 메모 리 를 낭비 할 것 이 며,통계 적 으로 64 비트 의 JVM 은 32 비트 의 JVM 보다 50%의 메모 리 를 더 소모 할 것 이다.메모 리 를 절약 하기 위해 옵션+UseCompressed Oops 를 사용 하여 포인터 압축 을 열 수 있 습 니 다.그 중에서 oop 은 ordinary object pointer 일반 대상 포인터 입 니 다.
이 옵션 을 선택 하면 다음 지침 은 32 비트 로 압축 됩 니 다.
각 Class 의 속성 포인터(즉 정적 변수)
각 대상 의 속성 포인터(즉 대상 변수)
일반 대상 배열 의 모든 요소 포인터
물론 모든 포인터 가 압축 되 는 것 도 아니 고 일부 특수 한 유형의 포인터 JVM 은 최적화 되 지 않 습 니 다.예 를 들 어 PermGen 을 가리 키 는 Class 대상 포인터(JDK 8 에서 원 공간 을 가리 키 는 Class 대상 포인터),로 컬 변수,스 택 요소,입 참,반환 값 과 NULL 포인터 등 입 니 다.
3.배열 길이
대상 이 하나의 배열 이 라면 대상 헤드 는 배열 의 길 이 를 저장 하 는 데 추가 공간 이 필요 합 니 다.이 부분의 데이터 길이 도 JVM 구조 에 따라 다 릅 니 다.32 비트 의 JVM 에서 길 이 는 32 비트 입 니 다.64 비트 JVM 은 64 비트 다.
64 비트 JVM+UseCompressedOops 옵션 을 열 면 이 영역 길이 도 64 비트 에서 32 비트 로 압축 됩 니 다.
이상 의 자바 대상 구조 대상 헤드 마크 워드 는 바로 편집장 이 여러분 에 게 공유 한 모든 내용 입 니 다.여러분 에 게 참고 가 되 고 여러분 들 이 저 희 를 많이 사랑 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기