您现在的位置是:亿华云 > 人工智能
Java中Unsafe使用详解
亿华云2025-10-09 04:00:49【人工智能】0人已围观
简介Unsafe介绍Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语
Unsafe介绍
Unsafe是用详位于sun.misc包下的一个类,主要提供一些用于执行低级别、用详不安全操作的用详方法,如直接访问系统内存资源、用详自主管理内存资源等,用详这些方法在提升Java运行效率、用详增强Java语言底层资源操作能力方面起到了很大的用详作用。但由于Unsafe类使得Java语言拥有了类似C语言指针一样操作内存空间的用详能力,这无疑也增加了程序发生相关指针问题的用详风险。在程序中过度、用详不正确使用Unsafe类会使得程序出错的用详概率变大,使得Java这种安全的用详语言变得不再“安全”,因此对Unsafe的用详使用一定要慎重。b2b信息网
java.util.concurrent.atomic包下的用详原子操作类,基本都是用详使用Unsafe实现的。
Unsafe提供的API大致可分为内存操作、CAS、Class、对象操作、线程、系统信息获取、内存屏障、数组操作等几类。
内存相关
CAS相关
java.util.concurrent.atomic包中的原子类基本都用的Unsafe
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); }线程相关
LockSupport类中有应用unpark,park
public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, 0L); setBlocker(t, null); } public static void unpark(Thread thread) { if (thread != null) UNSAFE.unpark(thread); }Class相关
对象操作相关
系统相关
内存屏障
loadFence:保证在这个屏障之前的所有读操作都已经完成。
storeFence:保证在这个屏障之前的所有写操作都已经完成。服务器托管
fullFence:保证在这个屏障之前的所有读写操作都已经完成。
在java8中 有这个StampedLock类,该类中应用了内存屏障功能。
private static final sun.misc.Unsafe U; static { try { U = sun.misc.Unsafe.getUnsafe(); } catch (Exception e) { throw new Error(e); } } public boolean validate(long stamp) { U.loadFence(); return (stamp & SBITS) == (state & SBITS); } U.loadFence();Unsafe.java
public final class Unsafe { private static native void registerNatives(); static { registerNatives(); sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe"); } private Unsafe() { } private static final Unsafe theUnsafe = new Unsafe(); // ... }获取Unsafe实例
Unsafe类是final且是单例的,并且theUnsafe字段是private;通过如下方法获取实例
方法1
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; theUnsafe.setAccessible(true) ; Unsafe unsafe = (Unsafe) theUnsafe.get(null) ;方法2
private static Unsafe unsafe = null ; static { try { Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ; cons.setAccessible(true) ; unsafe = cons.newInstance() ; } catch (Exception e) { e.printStackTrace(); } }Unsafe简单应用
int i = 0 ; public static void main(String[] args) throws Exception { UnsafeDemo d = new UnsafeDemo() ; // 获取Unsafe实例 Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; theUnsafe.setAccessible(true) ; Unsafe unsafe = (Unsafe) theUnsafe.get(null) ; // 获取类的实例变量 Field f = UnsafeDemo.class.getDeclaredField("i") ; // 获取字段相对Java对象的"起始地址"的偏移量 long fieldOffset = unsafe.objectFieldOffset(f) ; System.out.println(fieldOffset) ; // 设置值 boolean success = unsafe.compareAndSwapInt(d, fieldOffset, 0, 10) ; System.out.println(success) ; System.out.println(d.i) ; }Unsafe对象操作
private static Unsafe unsafe = null ; static { try { Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ; cons.setAccessible(true) ; unsafe = cons.newInstance() ; } catch (Exception e) { e.printStackTrace(); } } public static void allocate() { try { Person p = (Person)unsafe.allocateInstance(Person.class) ; p.setId("s001"); System.out.println(p.getValue()) ; System.out.println(p.getId()) ; } catch (Exception e) { e.printStackTrace(); } }执行结果:
对象操作2:
private Person p = new Person("1", "张三") ; public static void main(String[] args) throws Exception { UnSafeObjectDemo d = new UnSafeObjectDemo() ; Field field = Unsafe.class.getDeclaredField("theUnsafe") ; field.setAccessible(true) ; Unsafe unsafe = (Unsafe) field.get(null) ; Field f = d.getClass().getDeclaredField("p") ; long offset = unsafe.objectFieldOffset(f) ; System.out.println(offset) ; boolean res = unsafe.compareAndSwapObject(d, offset, d.p, new Person("2", "李四")) ; System.out.println(res) ; System.out.println(d.p.getName()) ; }Unsafe创建对象
当不知道即将使用的对象有何构造函数,或是不想使用现有对象的构造函数创建对象时,可以通过如下方式:
Constructor<Teacher> cons = (Constructor<Teacher>) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(Teacher.class, Object.class.getConstructor()); cons.setAccessible(true); Teacher t = cons.newInstance() ; System.out.println(t) ;Unsafe简单实现原子操作类
public class AtomicCount { private static Unsafe unsafe ; private int value ; private static long valueOffset ; static { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; theUnsafe.setAccessible(true) ; unsafe = (Unsafe) theUnsafe.get(null) ; Field f = AtomicCount.class.getDeclaredField("value") ; valueOffset = unsafe.objectFieldOffset(f) ; } catch (Exception e) { e.printStackTrace(); } } public AtomicCount(int value) { this.value = value ; } public final int get() { return value; } public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } }完毕!!!
亿华云计算很赞哦!(477)
相关文章
- 2、根据用户基础选择访问提供程序。由于互联问题的存在,接入商的选择也非常重要,如果用户群主要在联通,尽量选择联通接入较好的接入商,如果用户群主要在电信,那么选择电信接入较好的接入商。如果用户组位于国家/地区,则选择更好的访问提供程序进行交互。
- Github上近万Star!Codis,中国人开源的Redis集群部署解决方案
- 数据库并发2万就跪了?你需要这份指导性的知识框架
- Java 开发人员应该知道的五大 Spring Boot 特性
- 要如何了解反向解析和域名解析?新手该怎么去操作?
- Virtual DOM的历史和未来
- 达梦DM8新品发布 国产数据库迎来新的里程碑
- 让 Redis 这么快的 4 项黑科技,你知道是什么吗?
- 审核通过的域名将显示在域名竞拍页面,并进入正式拍卖期,买家可以在拍卖周期内出价,加价幅度与拍卖保证金说明,点此查看。
- 详解MySQL数据库JSON类型:用法、意义、内置函数