文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java中Unsafe使用详解

2024-12-03 07:27

关注

java.util.concurrent.atomic包下的原子操作类,基本都是使用Unsafe实现的。

Unsafe提供的API大致可分为内存操作、CAS、Class、对象操作、线程、系统信息获取、内存屏障、数组操作等几类。

内存相关

CAS相关

java.util.concurrent.atomic包中的原子类基本都用的Unsafe

  1. private static final Unsafe unsafe = Unsafe.getUnsafe(); 
  2. private static final long valueOffset; 
  3. static { 
  4.   try { 
  5.     valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value")); 
  6.   } catch (Exception ex) { throw new Error(ex); } 
  7. public final int getAndSet(int newValue) { 
  8.   return unsafe.getAndSetInt(this, valueOffset, newValue); 

线程相关

LockSupport类中有应用unpark,park

  1. public static void park(Object blocker) { 
  2.   Thread t = Thread.currentThread(); 
  3.   setBlocker(t, blocker); 
  4.   UNSAFE.park(false, 0L); 
  5.   setBlocker(t, null); 
  1. public static void unpark(Thread thread) { 
  2.   if (thread != null
  3.     UNSAFE.unpark(thread); 

Class相关

对象操作相关

系统相关

内存屏障

loadFence:保证在这个屏障之前的所有读操作都已经完成。

storeFence:保证在这个屏障之前的所有写操作都已经完成。

fullFence:保证在这个屏障之前的所有读写操作都已经完成。

在java8中 有这个StampedLock类,该类中应用了内存屏障功能。

  1. private static final sun.misc.Unsafe U; 
  2. static { 
  3.   try { 
  4.     U = sun.misc.Unsafe.getUnsafe(); 
  5.   } catch (Exception e) { 
  6.     throw new Error(e); 
  7.   } 
  8. public boolean validate(long stamp) { 
  9.   U.loadFence(); 
  10.   return (stamp & SBITS) == (state & SBITS); 

 

  1. U.loadFence(); 

 

Unsafe.java

  1. public final class Unsafe { 
  2.  
  3.     private static native void registerNatives(); 
  4.     static { 
  5.         registerNatives(); 
  6.         sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe"); 
  7.     } 
  8.  
  9.     private Unsafe() {} 
  10.  
  11.     private static final Unsafe theUnsafe = new Unsafe(); 
  12.     // ... 

获取Unsafe实例

Unsafe类是final且是单例的,并且theUnsafe字段是private;通过如下方法获取实例

方法1

  1. Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; 
  2. theUnsafe.setAccessible(true) ; 
  3. Unsafe unsafe = (Unsafe) theUnsafe.get(null) ; 

方法2

  1. private static Unsafe unsafe = null ; 
  2.      
  3. static { 
  4.     try { 
  5.         Constructor cons = Unsafe.class.getDeclaredConstructor() ; 
  6.         cons.setAccessible(true) ; 
  7.         unsafe = cons.newInstance() ; 
  8.     } catch (Exception e) { 
  9.         e.printStackTrace(); 
  10.     } 

Unsafe简单应用

  1. int i = 0 ; 
  2.      
  3. public static void main(String[] args) throws Exception { 
  4.     UnsafeDemo d = new UnsafeDemo() ; 
  5.     // 获取Unsafe实例 
  6.     Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; 
  7.     theUnsafe.setAccessible(true) ; 
  8.     Unsafe unsafe = (Unsafe) theUnsafe.get(null) ; 
  9.     // 获取类的实例变量 
  10.     Field f = UnsafeDemo.class.getDeclaredField("i") ; 
  11.     // 获取字段相对Java对象的"起始地址"的偏移量 
  12.     long fieldOffset = unsafe.objectFieldOffset(f) ; 
  13.     System.out.println(fieldOffset) ; 
  14.     // 设置值 
  15.     boolean success = unsafe.compareAndSwapInt(d, fieldOffset, 0, 10) ; 
  16.     System.out.println(success) ; 
  17.     System.out.println(d.i) ; 

Unsafe对象操作

  1. private static Unsafe unsafe = null ; 
  2.      
  3. static { 
  4. try { 
  5.         Constructor cons = Unsafe.class.getDeclaredConstructor() ; 
  6.         cons.setAccessible(true) ; 
  7.         unsafe = cons.newInstance() ; 
  8.     } catch (Exception e) { 
  9.         e.printStackTrace(); 
  10.     } 
  11. public static void allocate() { 
  12.     try { 
  13.         Person p = (Person)unsafe.allocateInstance(Person.class) ; 
  14.         p.setId("s001"); 
  15.         System.out.println(p.getValue()) ; 
  16.         System.out.println(p.getId()) ; 
  17.     } catch (Exception e) { 
  18.         e.printStackTrace(); 
  19.     } 

执行结果:

对象操作2:

  1. private Person p = new Person("1""张三") ; 
  2.      
  3. public static void main(String[] args) throws Exception { 
  4.   UnSafeObjectDemo d = new UnSafeObjectDemo() ; 
  5.   Field field = Unsafe.class.getDeclaredField("theUnsafe") ; 
  6.     field.setAccessible(true) ; 
  7.     Unsafe unsafe = (Unsafe) field.get(null) ; 
  8.     Field f = d.getClass().getDeclaredField("p") ; 
  9.     long offset = unsafe.objectFieldOffset(f) ; 
  10.     System.out.println(offset) ; 
  11.     boolean res = unsafe.compareAndSwapObject(d, offset, d.p, new Person("2""李四")) ; 
  12.     System.out.println(res) ; 
  13.     System.out.println(d.p.getName()) ; 

Unsafe创建对象

当不知道即将使用的对象有何构造函数,或是不想使用现有对象的构造函数创建对象时,可以通过如下方式:

  1. Constructor cons = (Constructor) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(Teacher.class, 
  2.                 Object.class.getConstructor()); 
  3. cons.setAccessible(true); 
  4. Teacher t = cons.newInstance() ; 
  5. System.out.println(t) ; 

Unsafe简单实现原子操作类

  1. public class AtomicCount { 
  2.      
  3.     private static Unsafe unsafe ; 
  4.      
  5.     private int value ; 
  6.     private static long valueOffset ; 
  7.      
  8.     static { 
  9.         try { 
  10.             Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; 
  11.             theUnsafe.setAccessible(true) ; 
  12.             unsafe = (Unsafe) theUnsafe.get(null) ; 
  13.              
  14.             Field f = AtomicCount.class.getDeclaredField("value") ; 
  15.             valueOffset = unsafe.objectFieldOffset(f) ; 
  16.         } catch (Exception e) { 
  17.             e.printStackTrace(); 
  18.         } 
  19.     } 
  20.      
  21.     public AtomicCount(int value) { 
  22.         this.value = value ; 
  23.     } 
  24.      
  25.     public final int get() { 
  26.         return value; 
  27.     } 
  28.      
  29.     public final int getAndIncrement() { 
  30.         return unsafe.getAndAddInt(this, valueOffset, 1); 
  31.     } 
  32.      

完毕!!!

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯