Java变量在内存_java 变量在内存中是如何表示的?

就HotSpot VM而言吧,ClassLoader在加载题主所举得例子类时,会对class文件的fields部分做解析,参见

Array* ClassFileParser::parse_fields(Symbol* class_name,

bool is_interface,

FieldAllocationCount *fac,

u2* java_fields_count_ptr, TRAPS){

//...

// The field array starts with tuples of shorts

// [access, name index, sig index, initial value index, byte offset].

// A generic signature slot only exists for field with generic

// signature attribute. And the access flag is set with

// JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE for that field. The generic

// signature slots are at the end of the field array and after all

// other fields data.

//

// f1: [access, name index, sig index, initial value index, low_offset, high_offset]

// f2: [access, name index, sig index, initial value index, low_offset, high_offset]

// ...

// fn: [access, name index, sig index, initial value index, low_offset, high_offset]

// [generic signature index]

// [generic signature index]

// ...

//

// Allocate a temporary resource array for field data. For each field,

// a slot is reserved in the temporary array for the generic signature

// index. After parsing all fields, the data are copied to a permanent

// array and any unused slots will be discarded.

//...

}

这个函数的代码部分我直接忽略了,有兴趣可以自己去看,贴出里面的注释部分,可见经过JVM解析后fields的数组的表现形式——数组中的每个用于表示Field域的具体信息是一个tuple,里面包含了JVM规范中对Field部分的具体定义;针对field的属性的解析,请参见:

// Parse attributes for a field.

void ClassFileParser::parse_field_attributes(u2 attributes_count,

bool is_static, u2 signature_index,

u2* constantvalue_index_addr,

bool* is_synthetic_addr,

u2* generic_signature_index_addr,

ClassFileParser::FieldAnnotationCollector* parsed_annotations,

TRAPS) {//...//}

开始回答题主的问题吧,假定题主对Oop-Klass对象二分模型已经有过学习,Class文件中定义的这些Fields都会存储于该类InstanceKlass的_fields成员变量中,这是一个C++类,OpenJDK1.8后位于JVM内存空间中的MetadataSpace——所谓的元空间中;关于InstanceKlass的Layout,参见:

// InstanceKlass layout:

// [C++ vtbl pointer ] Klass

// [subtype cache ] Klass

// [instance size ] Klass

// [java mirror ] Klass

// [super ] Klass

// [access_flags ] Klass

// [name ] Klass

// [first subklass ] Klass

// [next sibling ] Klass

// [array klasses ]

// [methods ]

// [local interfaces ]

// [transitive interfaces ]

// [fields ]

// [constants ]

// [class loader ]

// [source file name ]

// [inner classes ]

// [static field size ]

// [nonstatic field size ]

// [static oop fields size ]

// [nonstatic oop maps size ]

// [has finalize method ]

// [deoptimization mark bit ]

// [initialization state ]

// [initializing thread ]

// [Java vtable length ]

// [oop map cache (stack maps) ]

// [EMBEDDED Java vtable ] size in words = vtable_len

// [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size

// The embedded nonstatic oop-map blocks are short pairs (offset, length)

// indicating where oops are located in instances of this klass.

// [EMBEDDED implementor of the interface] only exist for interface

// [EMBEDDED host klass ] only exist for an anonymous class (JSR 292 enabled)

对于题主提出的:实例变量 public int a=9

对于Non-Static类型的Field,其初始化与Static类型的Field有显著差别,对于Static类型的Member Field,经过上面的ClassParser,其初始化值由Field中元素中的initial value index——位于ConstantPool中的字面常量9的索引决定;但是对于实例变量,在new之前,它在哪里,且听下文继续分解——

假定题主的测试类形如:

public class NonStaticFieldTest {

private int i = 9;

public NonStaticFieldTest() {

}

public int getI() {

return this.i;

}

}

javap后的字节码会是这种形状:

public class NonStaticFieldTest {

private int i;

public NonStaticFieldTest();

Code:

0: aload_0

1: invokespecial #10 // Method java/lang/Object."":()V

4: aload_0

5: bipush 9

7: putfield #12 // Field i:I

10: return

public int getI();

Code:

0: aload_0

1: getfield #12 // Field i:I

4: ireturn

}

看见那个空的构造函数中的字节码指令集了吧:

5: bipush 9

7: putfield #12 // Field i:I

总结陈词:对于实例变量,它的初始值存在于构造函数的字节码中,等待invokeSpecial指令去初始化;当然这个构造函数函数作为klass的一部分存储于元空间的方法区中。

——完

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值