java putorderedint_java编程之:Unsafe类

Unsafe类在jdk 源码的多个类中用到,这个类的提供了一些绕开JVM的更底层功能,基于它的实现可以提高效率。但是,它是一把双刃剑:正如它的名字所预示的那样,它是 Unsafe的,它所分配的内存需要手动free(不被GC回收)。Unsafe类,提供了JNI某些功能的简单替代:确保高效性的同时,使事情变得更简 单。

这篇文章主要是以下文章的整理、翻译。

http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/

1. Unsafe API的大部分方法都是native实现,它由105个方法组成,主要包括以下几类:

(1)Info相关。主要返回某些低级别的内存信息:addressSize(), pageSize()

(2)Objects相关。主要提供Object和它的域操纵方法:allocateInstance(),objectFieldOffset()

(3)Class相关。主要提供Class和它的静态域操纵方法:staticFieldOffset(),defineClass(),defineAnonymousClass(),ensureClassInitialized()

(4)Arrays相关。数组操纵方法:arrayBaseOffset(),arrayIndexScale()

(5)Synchronization相关。主要提供低级别同步原语(如基于CPU的CAS(Compare-And-Swap)原 语):monitorEnter(),tryMonitorEnter(),monitorExit(),compareAndSwapInt(),putOrderedInt()

(6)Memory相关。直接内存访问方法(绕过JVM堆直接操纵本地内存):allocateMemory(),copyMemory(),freeMemory(),getAddress(),getInt(),putInt()

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.yeepay.sxf.hashmaptest;2

3 importjava.lang.reflect.Field;4

5 importsun.misc.Unsafe;6

7 public classTestUnSafe {8

9 public static void main(String[] args) throwsNoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {10 //获取属性

11 Field f=Unsafe.class.getDeclaredField("theUnsafe");12 //13 f.setAccessible(true);14 //获取实例

15 Unsafe unsafe=(Unsafe) f.get(null);16

17 //实例化一个类

18 Player player=(Player) unsafe.allocateInstance(Player.class);19 //打印年龄 打印结果:0

20 System.out.println("TestUnSafe.enclosing_method()"+player.getAge());21

22 player.setAge(100);23

24 //打印结果100

25 System.out.println("TestUnSafe.main()"+player.getAge());26

27 }28

29 }30

31 /**

32 * 普通类33 *@authorsxf34 *35 */

36 classPlayer{37 //年龄

38 private int age=12;39

40 //构造函数私有化

41 privatePlayer(){42 this.age=50;43 }44

45 public intgetAge() {46 returnage;47 }48

49 public void setAge(intage) {50 this.age =age;51 }52 }

View Code

【一】

public native long objectFieldOffset(Field field);

==> 返回指定静态field的内存地址偏移量,在这个类的其他方法中这个值只是被用作一个访问

==>特定field的一个方式。这个值对于 给定的field是唯一的,并且后续对该方法的调用都应该返回相同的值

【二】

public native boolean compareAndSwapInt(Object obj, long offset, int expect, int update);

==>在obj的offset位置比较long field和期望的值,如果相同则更新。这个方法的操作应该是原子的,因此提供了一种不可中断的方式更新long field。成功返回true,不成功返回false

==>obj:包含要修改field的对象

==>offset:obj对象中long型field的偏移量

==>expect:希望field中存在的值

==>update:如果期望值expect与field的当前值相同,设置filed的值为这个新值

【三】

public native boolean compareAndSwapObject(Object obj, long offset, Object expect, Object update);

==>在obj的offset位置比较object field和期望的值,如果相同则更新。这个方法的操作应该是原子的,因此提供了一种不可中断的方式更新object field.成功返回true,不成功返回false

==>obj:包含要修改field的对象

==>offset:obj中object型field的偏移量

==>expect:希望field中存在的值

==>update:如果期望值expect与field的当前值相同,设置filed的值为这个新值

【四】

public native void putOrderedInt(Object obj, long offset, int value);

==>设置obj对象中offset偏移地址对应的整型field的值为指定值。这是一个有序或者有延迟的putIntVolatile方法,并且不保证值的改变被其他线程立即看到。只有在field被volatile修饰并且期望被意外修改的时候使用才有用。

==>obj:  包含要修改field的对象

==>offset:    obj中整型field的偏移量

==>value:   field将被设置的新值

【五】

public native void putOrderedLong(Object obj, long offset, long value);

==>设置obj对象中offset偏移地址对应的long型field的值为指定值。这是一个有序或者有延迟的putLongVolatile方法,并且不保证值的改变被其他线程立即看到。只有在field被volatile修饰并且期望被意外修改的时候使用才有用。

==>obj:包含需要修改field的对象

==>offset:obj中long型field的偏移量

==>value:field将被设置的新值

【六】

public native void putOrderedObject(Object obj, long offset, Object value);

==>设置obj对象中offset偏移地址对应的整型field的值为指定值。支持volatile store语义

==>obj:包含需要修改field的对象

==>offset:obj中整型field的偏移量

==>value:field将被设置的新值

【七】

public native void putIntVolatile(Object obj, long offset, int value);

==>设置obj对象中offset偏移地址对应的整型field的值为指定值。支持volatile store语义

==>obj: 包含需要修改field的对象

==>offset:obj中整型field的偏移量

==>value:field将被设置的新值

【八】

public native int getIntVolatile(Object obj, long offset);

==>获取obj对象中offset偏移地址对应的整型field的值,支持volatile load语义。

==>obj: 包含需要去读取的field的对象

==>offset:obj中整型field的偏移量

【九】

public native void putLongVolatile(Object obj, long offset, long value);

==>设置obj对象中offset偏移地址对应的long型field的值为指定值。

==>obj:包含需要修改field的对象

==>offset: obj中long型field的偏移量

==>value: field将被设置的新值

【十】

public native long getLongVolatile(Object obj, long offset);

==>获取obj对象中offset偏移地址对应的long型field的值,支持volatile load语义。

==> obj:包含需要去读取的field的对象

==>offset:obj中long型field的偏移量

【十一】

public native void putLong(Object obj, long offset, long value);

==>设置obj对象中offset偏移地址对应的long型field的值为指定值。

==>obj:包含需要修改field的对象

==>offset: obj中long型field的偏移量

==>value:field将被设置的新值

【十二】

public native long getLong(Object obj, long offset);

==> 获取obj对象中offset偏移地址对应的long型field的值

==>obj:包含需要去读取的field的对象

==>offset:obj中long型field的偏移量

【十三】

public native void putObjectVolatile(Object obj, long offset, Object value);

==> 设置obj对象中offset偏移地址对应的object型field的值为指定值。

==>obj:包含需要修改field的对象

==>offset:obj中object型field的偏移量

==>value:field将被设置的新值

【十四】

public native Object getObjectVolatile(Object obj, long offset);

==>获取obj对象中offset偏移地址对应的object型field的值,支持volatile load语义。

==>obj:包含需要去读取的field的对象

==>offset:  obj中object型field的偏移量

【十五】

public native int arrayBaseOffset(Class arrayClass);

==>获取给定数组中第一个元素的偏移地址。 为了存取数组中的元素,这个偏移地址与arrayIndexScale* 方法的非0返回值一起被使用

==>arrayClass:第一个元素地址被获取的class

==>返回:数组第一个元素 的偏移地址

【十六】

public native int arrayIndexScale(Class arrayClass);

==>获取用户给定数组寻址的换算因子.一个合适的换算因子不能返回的时候(例如:基本类型), 返回0.这个返回值能够与arrayBaseOffset 一起使用去存取这个数组class中的元素

【十七】

public native void unpark(Thread thread);

==>释放被park创建的在一个线程上的阻塞.这个方法也可以被使用来终止一个先前调用park导致的阻塞.这个操作操作时不安全的,因此线程必须保证是活的.这是java代码不是native代码

==>thread:  要解除阻塞的线程

【十八】

public native void park(boolean isAbsolute, long time);

==>阻塞一个线程直到unpark出现、线程被中断或者timeout时间到期。如果一个unpark调用已经出现了,这里只计数。timeout为0表示永不过期.当isAbsolute为true时,timeout是相对于新纪元之后的毫秒。否则这个值就是超时前的纳秒数。这个方法执行时也可能不合理地返回(没有具体原因)

==>isAbsolute:如果为true timeout的值是一个相对于新纪元之后的毫秒数

==>time:  可以是一个要等待的纳秒数,或者是一个相对于新纪元之后的毫秒数直到到达这个时间点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值