java中的Unsafe类浅析

unsafe类

java是无法直接访问操作系统底层的,可以通过Unsafe类来访问操作系统底层。Unsafe类可以提升Java运行效率。

Unsafe的大部分API都是native的方法,主要包括以下几类:

1)Class相关。主要提供Class和它的静态字段的操作方法。

2)Object相关。主要提供Object和它的字段的操作方法。

3)Arrray相关。主要提供数组及其中元素的操作方法。

4)并发相关。主要提供低级别同步原语,如CAS、线程调度、volatile、内存屏障等。

5)Memory相关。提供了直接内存访问方法(绕过Java堆直接操作本地内存),可做到像C一样自由利用系统内存资源。

6)系统相关。主要返回某些低级别的内存信息,如地址大小、内存页大小。

Class相关

//静态属性的偏移量,用于在对应的Class对象中读写静态属性
public native long staticFieldOffset(Field f);  

//判断是否需要初始化一个类
public native Object staticFieldBase(Field f);

//确保类被初始化
public native boolean shouldBeInitialized(Class<?> c);

//定义一个类,可用于动态创建类
public native void ensureClassInitialized(Class<?> c);

//定义一个匿名类,可用于动态创建类
public native Class<?> defineClass(String name, byte[] b, int off,
int len, ClassLoader loader, ProtectionDomain protectionDomain);

public native Class<?> defineAnonymousClass(Class<?> hostClass, 
byte[] data, Object[] cpPatches);

Object相关类

//获得对象的字段偏移量 
public native long objectFieldOffset(Field f); 

//获得给定对象地址偏移量的int值
public native int getInt(Object o, long offset);

//设置给定对象地址偏移量的int值
public native void putInt(Object o, long offset, int x);

123//创建对象,但并不会调用其构造方法。如果类未被初始化,将初始化类。
public native Object allocateInstance(Class<?> cls) throws  
InstantiationException;

数组相关

//返回数组中第一个元素的偏移地址
public native int arrayBaseOffset(Class<?> arrayClass);

//boolean、byte、short、char、int、long、float、double,及对象类型均有以
//下方法/** The value of {@code arrayBaseOffset(boolean[].class)} */
public static final int ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe.
arrayBaseOffset(boolean[].class);

//返回数组中每一个元素占用的大小
//boolean、byte、short、char、int、long、float、double,及对象类型均有以
//下方法
/** The value of {@code arrayIndexScale(boolean[].class)} */
public static final int ARRAY_BOOLEAN_INDEX_SCALE = 
theUnsafe.arrayIndexScale(boolean[].class);

并发相关

  • CAS相关

CAS:CompareAndSwap,内存偏移地址offset,预期值expected,新值x。如果变量在当前时刻的值和预期值expected相等,尝试将变量的值更新为x。如果更新成功,返回true;否则,返回false。

//更新变量值为x,如果当前值为expected
//o:对象 offset:偏移量 expected:期望值 x:新值
public final native boolean compareAndSwapObject(Object o,long offset,
Object expected,Object x);  

public final native boolean compareAndSwapInt(Object o, long offset,      
int expected,int x); 

public final native boolean compareAndSwapLong(Object o, long offset,      
long expected,long x);

从Java 8开始,Unsafe中提供了以下方法:

//增加
public final int getAndAddInt(Object o, long offset, int delta) {
  int v; 
  do{ 
      v = getIntVolatile(o, offset); 
    } while (!compareAndSwapInt(o, offset, v, v + delta)); 
  return v;
}  

public final long getAndAddLong(Object o, long offset, long delta){       
   long v;
   do { 
       v = getLongVolatile(o, offset); 
      } while (!compareAndSwapLong(o, offset, v, v + delta)); 
   return v;
}

//设置
public final int getAndSetInt(Object o, long offset, int newValue){   
  int v;
  do{ 
     v = getIntVolatile(o, offset);
    }while(!compareAndSwapInt(o, offset, v, newValue));
  return v;
}  

public final long getAndSetLong(Object o,long offset,long newValue){
   long v;
   do{ 
       v = getLongVolatile(o, offset); 
     } while (!compareAndSwapLong(o, offset, v, newValue)); 
   return v;
} 

public final Object getAndSetObject(Object o, long offset, 
Object newValue){ 
   Object v; 
   do{ 
      v = getObjectVolatile(o, offset); 
   }while (!compareAndSwapObject(o, offset, v, newValue)); 
   return v;
}
  • 线程调度相关
//取消阻塞线程
public native void unpark(Object thread);

//阻塞线程
public native void park(boolean isAbsolute, long time);

//获得对象锁
public native void monitorEnter(Object o);

//释放对象锁
public native void monitorExit(Object o);

//尝试获取对象锁,返回true或false表示是否获取成功
public native boolean tryMonitorEnter(Object o);
  • volatile相关读写

Java中的基本类型(boolean、byte、char、short、int、long、float、double)及对象引用类型都有以下方法。

//从对象的指定偏移量处获取变量的引用,使用volatile的加载语义
//相当于getObject(Object, long)的volatile版本
public native Object getObjectVolatile(Object o, long offset);

//存储变量的引用到对象的指定的偏移量处,使用volatile的存储语义
//相当于putObject(Object, long, Object)的volatile版本
public native void putObjectVolatile(Object o, long offset, Object x);

public native void putOrderedObject(Object o, long offset, Object x);
/** Ordered/Lazy version of {@link #putIntVolatile(Object, long, 
int)} */
public native void putOrderedInt(Object o, long offset, int x);  
/** Ordered/Lazy version of {@link #putLongVolatile(Object, long, 
long)} */
public native void putOrderedLong(Object o, long offset, long x);
  • 内存屏障相关

Java 8引入 ,用于定义内存屏障,避免代码重排序。

//内存屏障,禁止load操作重排序,即屏障前的load操作不能被重排序到屏障后,
//屏障后的load操作不能被重排序到屏障前
public native void loadFence();

//内存屏障,禁止store操作重排序,即屏障前的store操作不能被重排序到屏障后,
//屏障后的store操作不能被重排序到屏障前
public native void storeFence();

//内存屏障,禁止load、store操作重排序
public native void fullFence();

直接内存访问(非堆内存)

allocateMemory所分配的内存需要手动free(不被GC回收)

//(boolean、byte、char、short、int、long、float、double)都有以下get、put两个方法。 
//获得给定地址上的int值
public native int getInt(long address);
//设置给定地址上的int值
public native void putInt(long address, int x);
//获得本地指针
public native long getAddress(long address);
//存储本地指针到给定的内存地址
public native void putAddress(long address, long x);
 
//分配内存
public native long allocateMemory(long bytes);
//重新分配内存
public native long reallocateMemory(long address, long bytes);
//初始化内存内容
public native void setMemory(Object o, long offset, long bytes, byte value);
//初始化内存内容
public void setMemory(long address, long bytes, byte value) {
 setMemory(null, address, bytes, value);
}
//内存内容拷贝
public native void copyMemory(Object srcBase, long srcOffset,
    Object destBase, long destOffset,
    long bytes);
//内存内容拷贝
public void copyMemory(long srcAddress, long destAddress, long bytes) {
 copyMemory(null, srcAddress, null, destAddress, bytes);
}
//释放内存
public native void freeMemory(long address);

系统相关

//返回指针的大小。返回值为4或8。
public native int addressSize();
 
/** The value of {@code addressSize()} */
public static final int ADDRESS_SIZE = theUnsafe.addressSize();
 
//内存页的大小。
public native int pageSize();

来源于https://www.jb51.net/article/140726.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值