当前位置: 首页 > wzjs >正文

上海高中生做课题的网站佛山网站建设公司

上海高中生做课题的网站,佛山网站建设公司,网站制作工资,阿里云网站建设——部署与发布在Java反射机制中,访问对象的int类型字段值(如field.getInt(object))的底层实现涉及JVM对内存偏移量的计算与直接内存访问。本文通过分析OpenJDK 17源码,揭示这一过程的核心实现逻辑。 一、字段偏移量计算 1. Java层初始化偏移量…

在Java反射机制中,访问对象的int类型字段值(如field.getInt(object))的底层实现涉及JVM对内存偏移量的计算与直接内存访问。本文通过分析OpenJDK 17源码,揭示这一过程的核心实现逻辑。


一、字段偏移量计算

1. Java层初始化偏移量

反射访问字段时,会通过UnsafeFieldAccessorImpl初始化字段的偏移量:

UnsafeFieldAccessorImpl(Field field) {this.field = field;if (Modifier.isStatic(field.getModifiers()))fieldOffset = unsafe.staticFieldOffset(field);elsefieldOffset = unsafe.objectFieldOffset(field); // 实例字段偏移量isFinal = Modifier.isFinal(field.getModifiers());
}
  • 对于实例字段,调用Unsafe.objectFieldOffset(field)获取偏移量。

2. 本地方法调用

objectFieldOffset方法通过JNI调用C++实现:

public long objectFieldOffset(Field f) {return objectFieldOffset0(f); // 调用native方法
}
private native long objectFieldOffset0(Field f);
3. C++层计算偏移量

在JVM中,Unsafe_ObjectFieldOffset0最终调用find_field_offset函数:

UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset0(...)) {return find_field_offset(field, 0, THREAD);
} UNSAFE_ENDstatic jlong find_field_offset(...) {oop reflected = JNIHandles::resolve_non_null(field);Klass* k = java_lang_Class::as_Klass(mirror);int slot = java_lang_reflect_Field::slot(reflected); // 获取字段slotint offset = InstanceKlass::cast(k)->field_offset(slot); // 通过slot计算偏移量return field_offset_from_byte_offset(offset);
}
  • 字段slot:反射对象Field中存储的slot值对应类元数据(InstanceKlass)中字段的索引。

  • 偏移量计算InstanceKlass::field_offset(slot)通过slot索引从类元数据中获取字段的实际内存偏移量。


二、通过偏移量访问字段值

1. Java层读取字段值

反射调用getInt时,直接通过偏移量访问内存:

public int getInt(Object obj) {ensureObj(obj);return unsafe.getInt(obj, fieldOffset); // 使用偏移量读取int值
}
2. C++层内存访问

在JVM解释执行字节码时(如GETFIELD),访问字段的逻辑与反射一致:

// 字节码解释执行逻辑片段
case itos:SET_STACK_INT(obj->int_field(field_offset), -1);break;
  • obj->int_field(field_offset):通过偏移量直接从对象内存中读取int值。

  • SET_STACK_INT将值压入操作数栈。


三、关键数据结构与内存布局

1. 对象内存布局(oopDesc)

Java对象在内存中的布局包含对象头(Header)和实例数据(Instance Data):

  • 对象头:存储Mark Word和类指针(Klass*)。

  • 实例数据:字段按声明顺序排列,每个字段的偏移量由类元数据确定。

2. 类元数据(Klass)

InstanceKlass存储类的元信息,包括字段表:

class InstanceKlass : public Klass {// 字段表(fieldDescriptor数组)int field_offset(int slot) const {return field(slot)->offset(); // 获取字段偏移量}
};
3. 反射字段的slot映射

反射对象Field通过slot与类元数据关联:

// 反射Field对象存储slot值
int java_lang_reflect_Field::slot(oop reflect) {return reflect->int_field(_slot_offset);
}
  • slot值在类加载阶段生成,对应字段在类字段表中的索引。


四、性能优化与安全性

1. 偏移量缓存

反射调用Field.getInt()时,偏移量(fieldOffset)在UnsafeFieldAccessorImpl初始化阶段计算并缓存,后续访问无需重复计算。

2. 内存直接访问

通过Unsafe.getInt(obj, offset)绕过Java访问控制,直接操作内存。这种设计虽然高效,但也绕过了语言层面的安全性检查。

3. final字段处理

若字段为finalUnsafeFieldAccessorImpl会标记isFinal,部分JVM实现可能阻止修改(尽管某些场景下仍可通过反射修改)。


五、总结

通过反射访问int字段的流程可概括为:

  1. 计算偏移量:反射初始化阶段通过slot从类元数据获取字段偏移量。

  2. 内存访问:调用Unsafe.getInt()直接读取对象内存。

  3. 字节码执行:解释器/即时编译器使用相同机制访问字段。

这一机制体现了JVM反射与字节码执行在底层实现上的一致性:均依赖预先计算的字段偏移量直接操作内存。理解这一过程有助于优化反射性能,并为分析JVM内存模型提供基础。

openjdk17源码

UnsafeFieldAccessorImpl(Field field) {this.field = field;if (Modifier.isStatic(field.getModifiers()))fieldOffset = unsafe.staticFieldOffset(field);elsefieldOffset = unsafe.objectFieldOffset(field);isFinal = Modifier.isFinal(field.getModifiers());}public long objectFieldOffset(Field f) {if (f == null) {throw new NullPointerException();}return objectFieldOffset0(f);}private native long objectFieldOffset0(Field f);public int getInt(Object obj) throws IllegalArgumentException {ensureObj(obj);return unsafe.getInt(obj, fieldOffset);}} else if (type == Integer.TYPE) {return new UnsafeIntegerFieldAccessorImpl(field);}C++代码
{CC "objectFieldOffset0", CC "(" FLD ")J",           FN_PTR(Unsafe_ObjectFieldOffset0)},UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset0(JNIEnv *env, jobject unsafe, jobject field)) {return find_field_offset(field, 0, THREAD);
} UNSAFE_ENDstatic jlong find_field_offset(jobject field, int must_be_static, TRAPS) {assert(field != NULL, "field must not be NULL");oop reflected   = JNIHandles::resolve_non_null(field);oop mirror      = java_lang_reflect_Field::clazz(reflected);Klass* k        = java_lang_Class::as_Klass(mirror);int slot        = java_lang_reflect_Field::slot(reflected);int modifiers   = java_lang_reflect_Field::modifiers(reflected);if (must_be_static >= 0) {int really_is_static = ((modifiers & JVM_ACC_STATIC) != 0);if (must_be_static != really_is_static) {THROW_0(vmSymbols::java_lang_IllegalArgumentException());}}int offset = InstanceKlass::cast(k)->field_offset(slot);return field_offset_from_byte_offset(offset);
}int     field_offset      (int index) const { return field(index)->offset(); }int java_lang_reflect_Field::slot(oop reflect) {return reflect->int_field(_slot_offset);
}void java_lang_reflect_Field::set_slot(oop reflect, int value) {reflect->int_field_put(_slot_offset, value);
}oop Reflection::new_field(fieldDescriptor* fd, TRAPS) {Symbol*  field_name = fd->name();oop name_oop = StringTable::intern(field_name, CHECK_NULL);Handle name = Handle(THREAD, name_oop);Symbol*  signature  = fd->signature();InstanceKlass* holder = fd->field_holder();Handle type = new_type(signature, holder, CHECK_NULL);Handle rh  = java_lang_reflect_Field::create(CHECK_NULL);java_lang_reflect_Field::set_clazz(rh(), fd->field_holder()->java_mirror());java_lang_reflect_Field::set_slot(rh(), fd->index());inline jint oopDesc::int_field(int offset) const                    { return HeapAccess<>::load_at(as_oop(), offset);  }
inline jint oopDesc::int_field_raw(int offset) const                { return RawAccess<>::load_at(as_oop(), offset);   }
inline void oopDesc::int_field_put(int offset, jint value)          { HeapAccess<>::store_at(as_oop(), offset, value); }case stos:SET_STACK_INT(obj->short_field(field_offset), -1);break;case itos:SET_STACK_INT(obj->int_field(field_offset), -1);#define DEFINE_GETSETOOP(java_type, Type) \\
UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \return MemoryAccess<java_type>(thread, obj, offset).get(); \
} UNSAFE_END \T get() {if (_obj == NULL) {GuardUnsafeAccess guard(_thread);T ret = RawAccess<>::load(addr());return normalize_for_read(ret);} else {T ret = HeapAccess<>::load_at(_obj, _offset);return normalize_for_read(ret);}}

http://www.dtcms.com/wzjs/416712.html

相关文章:

  • 哪些企业网站做的好什么软件可以发布推广信息
  • 网站开发技术 文库绍兴seo推广
  • 明水县网站建设佛山快速排名seo
  • 上海中学官网电脑版做网站优化推广
  • 微信 小程序 wordpress优化站点
  • 做招聘网站公司北京网站营销seo方案
  • 网站设计公司 中山一个产品的市场营销策划方案
  • 开展网站建设性价比高seo排名
  • 免费加速器看国外网站免费引流推广怎么做
  • php mysql 网站源码seo优化信
  • 北京网站建设的服务商品牌咨询
  • 成都装饰网站建设免费建一个自己的网站
  • 个人做收费网站外贸网站都有哪些
  • 西安网站制作开发网站关键词百度自然排名优化
  • 国内外贸免费网站建设百度网盘客服24小时电话人工服务
  • 微信模板图片福州seo代理商
  • 长春网站上排名电脑培训学校哪家最好
  • 如何做自适应网站网站推广渠道
  • 软件技术专升本考什么科目百度爱采购优化排名软件
  • 有人从搜索引擎找网站建设吗网站建设培训
  • 优秀的浏览器主页北京seo顾问推推蛙
  • 电子商务怎样建立网站的百度seo发帖推广
  • 毕业设计做网站答辩会问什么佛山网站建设
  • 3g手机网站建设竞价推广专员
  • 网站建设从入门到精通 网盘太原自动seo
  • 天津市政府网站建设管理东莞免费网站建设网络营销
  • 正定网站制作企业推广策划公司
  • 黑龙江省建设教育信息网站宁波seo网络推广外包报价
  • 电子政务网站建设公司排行榜最近比较火的关键词
  • 网站建设功能文档廊坊网站推广公司