java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值
来源:互联网 发布:java 函数形参和实参 编辑:程序博客网 时间:2024/06/11 22:00
在上一篇文章中,我们列出了计算java对象大小的几个结论以及jol工具的使用,jol工具的源码有兴趣的可以去看下。现在我们利用JDK中的sun.misc.Unsafe来计算下字段的偏移地址,一则验证下之前文章中的结论,再则跟jol输出结果对比下。如何获取sun.misc.Unsafe对象,可以参考这篇文章。
public class VO{public int a = 0;public long b = 0;public static String c= "123";public static Object d= null;public static int e = 100;}
1.获取实例字段的偏移地址
// 获取实例字段的偏移地址,偏移最小的那个字段(仅挨着头部)就是对象头的大小System.out.println(unsafe.objectFieldOffset(VO.class.getDeclaredField("a")));System.out.println(unsafe.objectFieldOffset(VO.class.getDeclaredField("b")));// fieldOffset与objectFieldOffset功能一样,fieldOffset是过时方法,最好不要再使用System.out.println(unsafe.fieldOffset(VO.class.getDeclaredField("b")));
2.获取数组的头部大小和元素大小
// 数组第一个元素的偏移地址,即数组头占用的字节数int[] intarr = new int[0];System.out.println(unsafe.arrayBaseOffset(intarr.getClass()));// 数组中每个元素占用的大小System.out.println(unsafe.arrayIndexScale(intarr.getClass()));Unsafe类中有很多以BASE_OFFSET结尾的常量,比如ARRAY_INT_BASE_OFFSET等,这些常量值是通过arrayBaseOffset方法得到的。arrayBaseOffset方法是一个本地方法,可以获取数组第一个元素的偏移地址。Unsafe类中还有很多以INDEX_SCALE结尾的常量,比如 ARRAY_INT_INDEX_SCALE 等,这些常量值是通过arrayIndexScale方法得到的。将arrayBaseOffset与arrayIndexScale配合使用,可以定位数组中每个元素在内存中的位置。
3.获取类的静态字段偏移
// 获取类的静态字段偏地址System.out.println(unsafe.staticFieldOffset(VO.class.getDeclaredField("c")));System.out.println(unsafe.staticFieldOffset(VO.class.getDeclaredField("d")));// 获取静态字段的起始地址,通过起始地址和偏移地址,就可以获取静态字段的值了// 只不过静态字段的起始地址,类型不是long,而是Object类型Object base1 = unsafe.staticFieldBase(VO.class);Object base2 = unsafe.staticFieldBase(VO.class.getDeclaredField("d"));System.out.println(base1==base2);//true
4.获取操作系统的位数
// Report the size in bytes of a native pointer.// 返回4或8,代表是32位还是64位操作系统。System.out.println(unsafe.addressSize());// 返回32或64,获取操作系统是32位还是64位System.out.println(System.getProperty("sun.arch.data.model"));
5.读取对象实例字段的值
//获取实例字段的属性值VO vo = new VO();vo.a = 10000;long aoffset = unsafe.objectFieldOffset(VO.class.getDeclaredField("a"));int va = unsafe.getInt(vo, aoffset);System.out.println("va="+va);
6.获取静态字段的属性值
VO.e = 1024;Field sField = VO.class.getDeclaredField("e");Object base = unsafe.staticFieldBase(sField);long offset = unsafe.staticFieldOffset(sField);System.out.println(unsafe.getInt(base, offset));//1024
可以看到Unsafe功能是很强大的,位java语言提供了更底层的功能。
0 0
- java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值
- 使用sun.misc.Unsafe获取java对象地址
- 使用sun.misc.Unsafe获取java对象地址
- sun.misc.unsafe类的使用
- sun.misc.unsafe类的使用
- sun.misc.unsafe类的使用
- sun.misc.unsafe类的使用
- sun.misc.unsafe类的使用
- sun.misc.unsafe类的使用
- sun.misc.unsafe类的使用
- sun.misc.unsafe魔术类的使用
- sun.misc.unsafe类的使用
- sun.misc.unsafe类的使用
- sun.misc.Unsafe的理解
- sun.misc.Unsafe的各种神技
- 【转载】sun.misc.Unsafe的理解
- sun.misc.Unsafe的各种神技
- 4.锁--sun.misc.unsafe类的使用
- WPF 颜色
- 如何产生一个从x到y的k个随机数 Random(int x,int y ,int k)
- linux mv命令
- shell学习第七天----基础正则表达式(BRE)
- cocoStudio: button触摸事件响应
- java对象的内存布局(二):利用sun.misc.Unsafe获取类字段的偏移地址和读取字段的值
- 基于am3358的led跑马灯测试
- 带箭头的曲线(自定义的贝塞尔曲线和首次启动 app的引导界面)
- GridView的标准写法
- 微信支付 V3版
- 学习嵌入式系统可以分为哪几个阶段呢?
- backbone.js 路由 模版 使用示例
- 移动应用界面设计的尺寸设置及规范
- top命令详解