• 如果您觉得本站非常有看点，那么赶紧使用Ctrl+D 收藏吧

# 字段解析（3）

2周前 (07-31) 17次浏览

```FieldLayoutInfo info;
```

### 1、静态变量的偏移量

```int next_static_oop_offset;
int next_static_double_offset;
int next_static_word_offset;
int next_static_short_offset;
int next_static_byte_offset;

...

// Calculate the starting byte offsets
next_static_oop_offset      = InstanceMirrorKlass::offset_of_static_fields();
next_static_double_offset   = next_static_oop_offset + (  (fac->count[STATIC_OOP]) * heapOopSize  );
if ( fac->count[STATIC_DOUBLE] &&
(
Universe::field_type_should_be_aligned(T_DOUBLE) ||  // 方法会返回true
Universe::field_type_should_be_aligned(T_LONG)       // 方法会返回true
)
){
next_static_double_offset = align_size_up(next_static_double_offset, BytesPerLong);
}
next_static_word_offset     = next_static_double_offset + ((fac->count[STATIC_DOUBLE]) * BytesPerLong);
next_static_short_offset    = next_static_word_offset + ((fac->count[STATIC_WORD]) * BytesPerInt);
next_static_byte_offset     = next_static_short_offset + ((fac->count[STATIC_SHORT]) * BytesPerShort);
```

```static void init_offset_of_static_fields() {
// java.lang.Class类使用InstanceMirrorKlass对象来表示，而java.lang.Class对象通过Oop对象来表示，那么imk->size_helper()获取的就是
// Oop对象的大小，左移3位将字转换为字节
InstanceMirrorKlass* imk = InstanceMirrorKlass::cast(SystemDictionary::Class_klass());
_offset_of_static_fields = imk->size_helper() << LogHeapWordSize; // LogHeapWordSize=3
}
```

### 2、非静态变量的偏移量

```int nonstatic_field_size = _super_klass() == NULL ? 0 : _super_klass()->nonstatic_field_size();
...
int nonstatic_fields_start  = instanceOopDesc::base_offset_in_bytes() + nonstatic_field_size * heapOopSize;
next_nonstatic_field_offset = nonstatic_fields_start;
```

```// If compressed, the offset of the fields of the instance may not be aligned.
static int base_offset_in_bytes() {
// offset computation code breaks if UseCompressedClassPointers
// only is true
return ( UseCompressedOops && UseCompressedClassPointers ) ?
klass_gap_offset_in_bytes() :  // 开启指针压缩后计算出来的值为12
sizeof(instanceOopDesc);       // 在64位上计算出来为16
}
```

```// 在类上加@Contended注解的说明可参考：https://www.icode9.com/content-1-375023.html
bool is_contended_class     = parsed_annotations->is_contended();
// Class is contended, pad before all the fields
if (is_contended_class) {
}

// Compute the non-contended fields count.
// The packing code below relies on these counts to determine if some field
// can be squeezed into the alignment gap. Contended fields are obviously exempt from that.
unsigned int nonstatic_double_count = fac->count[NONSTATIC_DOUBLE] - fac_contended.count[NONSTATIC_DOUBLE];
unsigned int nonstatic_word_count   = fac->count[NONSTATIC_WORD]   - fac_contended.count[NONSTATIC_WORD];
unsigned int nonstatic_short_count  = fac->count[NONSTATIC_SHORT]  - fac_contended.count[NONSTATIC_SHORT];
unsigned int nonstatic_byte_count   = fac->count[NONSTATIC_BYTE]   - fac_contended.count[NONSTATIC_BYTE];
unsigned int nonstatic_oop_count    = fac->count[NONSTATIC_OOP]    - fac_contended.count[NONSTATIC_OOP];

// Total non-static fields count, including every contended field
unsigned int nonstatic_fields_count = fac->count[NONSTATIC_DOUBLE] +
fac->count[NONSTATIC_WORD]   +
fac->count[NONSTATIC_SHORT]  +
fac->count[NONSTATIC_BYTE]   +
fac->count[NONSTATIC_OOP];
```

• allocation_style=0，字段排列顺序为oops、longs/doubles、ints、shorts/chars、bytes，最后是填充字段，以满足对齐要求；
• allocation_style=1，字段排列顺序为longs/doubles、ints、shorts/chars、bytes、oops，最后是填充字段，以满足对齐要求；
• allocation_style=2，JVM在布局时会尽量使父类oops和子类oops挨在一起。

```bool compact_fields   = CompactFields;         // 默认值为true
int  allocation_style = FieldsAllocationStyle; // 默认的布局为1
// ...

// Rearrange fields for a given allocation style
if( allocation_style == 0 ) {
// Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
next_nonstatic_oop_offset    = next_nonstatic_field_offset;  // 首先布局oop类型的变量
next_nonstatic_double_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
}
else if( allocation_style == 1 ) {
// Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
next_nonstatic_double_offset = next_nonstatic_field_offset; // 首先布局long/double类型的变量
}
else if( allocation_style == 2 ) {
// Fields allocation: oops fields in super and sub classes are together.
if(
nonstatic_field_size > 0 && // nonstatic_field_size指的是父类的非静态变量占用的大小
_super_klass() != NULL &&
_super_klass->nonstatic_oop_map_size() > 0
){
unsigned int  map_count = _super_klass->nonstatic_oop_map_count();
OopMapBlock*  first_map = _super_klass->start_of_nonstatic_oop_maps();
OopMapBlock*  last_map  = first_map + map_count - 1;
int next_offset = last_map->offset() + (last_map->count() * heapOopSize);
if (next_offset == next_nonstatic_field_offset) {
allocation_style = 0;   // allocate oops first
next_nonstatic_oop_offset    = next_nonstatic_field_offset;
next_nonstatic_double_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
}
}

if( allocation_style == 2 ) {
allocation_style = 1;     // allocate oops last
next_nonstatic_double_offset = next_nonstatic_field_offset;
}
}
else {
ShouldNotReachHere();
}
```

```// count
int nonstatic_oop_space_count   = 0;
int nonstatic_word_space_count  = 0;
int nonstatic_short_space_count = 0;
int nonstatic_byte_space_count  = 0;
// offset
int nonstatic_oop_space_offset;
int nonstatic_word_space_offset;
int nonstatic_short_space_offset;
int nonstatic_byte_space_offset;

// Try to squeeze some of the fields into the gaps due to long/double alignment.
// 向补白空隙中填充字段，填充的顺序为int、short、byte、oopmap
if( nonstatic_double_count > 0 ) { // 当有long/double类型的实例变量存在时，可能存在空隙
int offset = next_nonstatic_double_offset;
next_nonstatic_double_offset = align_size_up(offset, BytesPerLong);
// 只有开启了-XX:+CompactFields命令时才会进行空白填充
if( compact_fields && offset != next_nonstatic_double_offset ) {
// Allocate available fields into the gap before double field.
int length = next_nonstatic_double_offset - offset;
assert(length == BytesPerInt, "");
// nonstatic_word_count记录了word的总数，由于这个gap算一个特殊位置，故把放入这里的word从正常情况删除，
// 并加入特殊的nonstatic_word_space_count中。
nonstatic_word_space_offset = offset;
if( nonstatic_word_count > 0 ) { // 由于long/double是8字节对齐，所以最多只能有7个字节的空隙，最多只能填充一个word类型的变量
nonstatic_word_count      -= 1;
nonstatic_word_space_count = 1; // Only one will fit
length -= BytesPerInt;
offset += BytesPerInt;
}
nonstatic_short_space_offset = offset;
while( length >= BytesPerShort && nonstatic_short_count > 0 ) {
nonstatic_short_count       -= 1;
nonstatic_short_space_count += 1;
length -= BytesPerShort;
offset += BytesPerShort;
}
nonstatic_byte_space_offset = offset;
while( length > 0 && nonstatic_byte_count > 0 ) {
nonstatic_byte_count       -= 1;
nonstatic_byte_space_count += 1;
length -= 1;
}
// Allocate oop field in the gap if there are no other fields for that.
nonstatic_oop_space_offset = offset;
// when oop fields not first
// heapOopSize在开启指针压缩时为4,否则为8,所以一个oop占用的字节数要看heapOopSize的大小，理论上空隙也最多
// 只能存放一个oop对象
// allocation_style必须不等于0,因为等于0时，oop要分配到开始的位置，和父类的oop进行连续存储，不能
// 进行空隙填充
if( length >= heapOopSize && nonstatic_oop_count > 0 && allocation_style != 0 ) {
nonstatic_oop_count      -= 1;
nonstatic_oop_space_count = 1; // Only one will fit
length -= heapOopSize;
offset += heapOopSize;
}
}
}
```

long/double类型占用8字节，对齐时，最多可能留下7字节的空白。Java数据类型与JVM内部定义的5种数据类型的对应关系如下表所示。

 Java数据类型 JVM内部数据类型 数据宽度 reference oop 4字节（指针压缩）/8字节 boolean/byte byte 1字节 char/short short 2字节 int/float word 4字节 long/double double 8字节

```next_nonstatic_word_offset   = next_nonstatic_double_offset + (nonstatic_double_count * BytesPerLong);
next_nonstatic_short_offset  = next_nonstatic_word_offset   + (nonstatic_word_count * BytesPerInt);
next_nonstatic_byte_offset   = next_nonstatic_short_offset  + (nonstatic_short_count * BytesPerShort);

// let oops jump before padding with this allocation style
// 为1时的布局为： // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields
if( allocation_style == 1 ) {
if( nonstatic_oop_count > 0 ) {
next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize);
}
next_nonstatic_padded_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize);
}
```

### 3、计算每个变量的偏移量

```// Iterate over fields again and compute correct offsets.
// The field allocation type was temporarily stored in the offset slot.
// oop fields are located before non-oop fields (static and non-static).
for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set())
continue;
// contended instance fields are handled below
if (fs.is_contended() && !fs.access_flags().is_static()){
continue; // 这个循环逻辑不处理有@Contended注解的实例变量
}
int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();

// pack the rest of the fields
switch (atype) {
case STATIC_OOP:
real_offset = next_static_oop_offset;
next_static_oop_offset += heapOopSize;
break;
case STATIC_BYTE:
real_offset = next_static_byte_offset;
next_static_byte_offset += 1;
break;
case STATIC_SHORT:
real_offset = next_static_short_offset;
next_static_short_offset += BytesPerShort;
break;
case STATIC_WORD:
real_offset = next_static_word_offset;
next_static_word_offset += BytesPerInt;
break;
case STATIC_DOUBLE:
real_offset = next_static_double_offset;
next_static_double_offset += BytesPerLong;
break;
case NONSTATIC_OOP:
if( nonstatic_oop_space_count > 0 ) {
real_offset = nonstatic_oop_space_offset;
nonstatic_oop_space_offset += heapOopSize;
nonstatic_oop_space_count  -= 1;
} else {
real_offset = next_nonstatic_oop_offset;
next_nonstatic_oop_offset += heapOopSize;
}
// Update oop maps
if(
nonstatic_oop_map_count > 0 &&
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
real_offset - int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) * heapOopSize
){
// Extend current oop map
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
} else {
// Create new oop map
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
nonstatic_oop_map_count += 1;
if( first_nonstatic_oop_offset == 0 ) { // Undefined
first_nonstatic_oop_offset = real_offset;
}
}
break;
case NONSTATIC_BYTE:
if( nonstatic_byte_space_count > 0 ) {
real_offset = nonstatic_byte_space_offset;
nonstatic_byte_space_offset += 1;
nonstatic_byte_space_count  -= 1;
} else {
real_offset = next_nonstatic_byte_offset;
next_nonstatic_byte_offset += 1;
}
break;
case NONSTATIC_SHORT:
if( nonstatic_short_space_count > 0 ) {
real_offset = nonstatic_short_space_offset;
nonstatic_short_space_offset += BytesPerShort;
nonstatic_short_space_count  -= 1;
} else {
real_offset = next_nonstatic_short_offset;
next_nonstatic_short_offset += BytesPerShort;
}
break;
case NONSTATIC_WORD:
if( nonstatic_word_space_count > 0 ) {
real_offset = nonstatic_word_space_offset;
nonstatic_word_space_offset += BytesPerInt;
nonstatic_word_space_count  -= 1;
} else {
real_offset = next_nonstatic_word_offset;
next_nonstatic_word_offset += BytesPerInt;
}
break;
case NONSTATIC_DOUBLE:
real_offset = next_nonstatic_double_offset;
next_nonstatic_double_offset += BytesPerLong;
break;
default:
ShouldNotReachHere();
} // end switch

fs.set_offset(real_offset);  // 设置真正的偏移量
} // end for
```

### 4、@Contended变量的偏移量

```// Handle the contended cases.
//
// Each contended field should not intersect the cache line with another contended field.
// In the absence of alignment information, we end up with pessimistically separating
// the fields with full-width padding.
//
// Additionally, this should not break alignment for the fields, so we round the alignment up
// for each field.
if (nonstatic_contended_count > 0) { // 标注有@Contended注解的字段数量

// if there is at least one contended field, we need to have pre-padding for them

// collect all contended groups
BitMap bm(_cp->size());
for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set()){
continue;
}
if (fs.is_contended()) {
bm.set_bit(fs.contended_group());
}
}
// 将同一组的@Contended变量布局在一起
int current_group = -1;
while ((current_group = (int)bm.get_next_one_offset(current_group + 1)) != (int)bm.size()) {
for (AllFieldStream fs(_fields, _cp); !fs.done(); fs.next()) {
// skip already laid out fields
if (fs.is_offset_set())
continue;
// skip non-contended fields and fields from different group
if (!fs.is_contended() || (fs.contended_group() != current_group))
continue;
// handle statics below
if (fs.access_flags().is_static())
continue;

int real_offset;
FieldAllocationType atype = (FieldAllocationType) fs.allocation_type();

switch (atype) {
case NONSTATIC_BYTE:
break;
case NONSTATIC_SHORT:
break;
case NONSTATIC_WORD:
break;
case NONSTATIC_DOUBLE:
break;
case NONSTATIC_OOP:

// Create new oop map
assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
nonstatic_oop_map_count += 1;
if( first_nonstatic_oop_offset == 0 ) { // Undefined
first_nonstatic_oop_offset = real_offset;
}
break;
default:
ShouldNotReachHere();
}

if (fs.contended_group() == 0) {
// Contended group defines the equivalence class over the fields:
// the fields within the same contended group are not inter-padded.
// The only exception is default group, which does not incur the
// equivalence, and so requires intra-padding.
}

fs.set_offset(real_offset);
} // end for

// Start laying out the next group.
// Note that this will effectively pad the last group in the back;
// this is expected to alleviate memory contention effects for
// subclass fields and/or adjacent object.
// If this was the default group, the padding is already in place.
if (current_group != 0) {
}
} // end while

// handle static fields
}```

1、在Ubuntu 16.04上编译OpenJDK8的源代码

2、调试HotSpot源代码

3、HotSpot项目结构

4、HotSpot的启动过程

5、HotSpot二分模型（1）

6、HotSpot的类模型（2）

7、HotSpot的类模型（3）

8、HotSpot的类模型（4）

9、HotSpot的对象模型（5）

10、HotSpot的对象模型（6）

11、操作句柄Handle（7）

12、句柄Handle的释放（8）

13、类加载器

14、类的双亲委派机制

15、核心类的预装载

16、Java主类的装载

17、触发类的装载

18、类文件介绍

19、文件流

20、解析Class文件

21、常量池解析（1）

22、常量池解析（2）

23、字段解析（1）

24、字段解析之伪共享（2）

（1）成员变量重排序