Unsafe

Unsafe类是什么呢?java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作。或许在读源码时候会发现,LockSupport里面会调用到unsafe.park,undafe.unpark,而同样在AQS里面会调用到unsafe里面众多CAS相关代码。
这些天在看源码时候,总会遇到park,unpark,CAS相关指令,都是从Unsafe里面调用,所以就花了点时间整体的阅读了Unsafe的源码,注释了所有方法,里面方法基本是native,这篇文章没有去深究相关方法c++实现,我的其他博文会有相关方法的深究~

概念

字段的定位:
JAVA中对象的字段的定位可能通过staticFieldOffset方法实现,该方法返回给定field的内存地址偏移量,这个值对于给定的filed是唯一的且是固定不变的。

  • getIntVolatile方法获取对象中offset偏移地址对应的整型field的值,volatile方式获取int值
  • getLong方法获取对象中offset偏移地址对应的long型field的值

数组元素定位:
Unsafe类中有很多以BASE_OFFSET结尾的常量,比如ARRAY_INT_BASE_OFFSET,ARRAY_BYTE_BASE_OFFSET等,这些常量值是通过arrayBaseOffset方法得到的。arrayBaseOffset方法是一个本地方法,可以获取数组第一个元素的偏移地址。Unsafe类中还有很多以INDEX_SCALE结尾的常量,比如 ARRAY_INT_INDEX_SCALE , ARRAY_BYTE_INDEX_SCALE等,这些常量值是通过arrayIndexScale方法得到的。arrayIndexScale方法也是一个本地方法,可以获取数组的转换因子,也就是数组中元素的增量地址。将arrayBaseOffset与arrayIndexScale配合使用,可以定位数组中每个元素在内存中的位置。

源码

Unsafe源代码地址:http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/07011844584f/src/share/classes/sun/misc/Unsafe.java

下面看带注释的代码:

/*** * @author John R. Rose* @see #getUnsafe* * 用getUnsafe来获取unsafe实例。* 大部分方法是底层级的,直接对应着硬件的指令。*/
public final class Unsafe {private static native void registerNatives();static {registerNatives();sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class,"getUnsafe");}private Unsafe() {}//final类型,保证会被正确初始化private static final Unsafe theUnsafe = new Unsafe();//获取unsafe实例的操作。@CallerSensitivepublic static Unsafe getUnsafe() {Class<?> caller = Reflection.getCallerClass();//判断caller的类加载器是否为系统类加载器。if (!VM.isSystemDomainLoader(caller.getClassLoader()))throw new SecurityException("Unsafe");return theUnsafe;}// 以下是一些读内存和写内存的操作。主要是从Java堆中。//并且以下方法不会作用与数组和引用。// 获取o的偏移地址为offset的int值。public native int getInt(Object o, long offset);//在o的偏移地址为offset处存储x。public native void putInt(Object o, long offset, int x);//获取o的偏移地址为offset的Object类型的引用的值。public native Object getObject(Object o, long offset);//下面方法同上public native void putObject(Object o, long offset, Object x);/** @see #getInt(Object, long) */public native boolean getBoolean(Object o, long offset);/** @see #putInt(Object, int, int) */public native void putBoolean(Object o, long offset, boolean x);/** @see #getInt(Object, long) */public native byte getByte(Object o, long offset);/** @see #putInt(Object, int, int) */public native void putByte(Object o, long offset, byte x);/** @see #getInt(Object, long) */public native short getShort(Object o, long offset);/** @see #putInt(Object, int, int) */public native void putShort(Object o, long offset, short x);/** @see #getInt(Object, long) */public native char getChar(Object o, long offset);/** @see #putInt(Object, int, int) */public native void putChar(Object o, long offset, char x);/** @see #getInt(Object, long) */public native long getLong(Object o, long offset);/** @see #putInt(Object, int, int) */public native void putLong(Object o, long offset, long x);/** @see #getInt(Object, long) */public native float getFloat(Object o, long offset);/** @see #putInt(Object, int, int) */public native void putFloat(Object o, long offset, float x);/** @see #getInt(Object, long) */public native double getDouble(Object o, long offset);/** @see #putInt(Object, int, int) */public native void putDouble(Object o, long offset, double x);// 以下主要在c语言堆上分配内存相关操作。//从特定内存地址里面获得byte值,没有则为undefinedpublic native byte getByte(long address);//把byte x的值放入到address处内存地址。public native void putByte(long address, byte x);/** @see #getByte(long) */public native short getShort(long address);/** @see #putByte(long, byte) */public native void putShort(long address, short x);/** @see #getByte(long) */public native char getChar(long address);/** @see #putByte(long, byte) */public native void putChar(long address, char x);/** @see #getByte(long) */public native int getInt(long address);/** @see #putByte(long, byte) */public native void putInt(long address, int x);/** @see #getByte(long) */public native long getLong(long address);/** @see #putByte(long, byte) */public native void putLong(long address, long x);/** @see #getByte(long) */public native float getFloat(long address);/** @see #putByte(long, byte) */public native void putFloat(long address, float x);/** @see #getByte(long) */public native double getDouble(long address);/** @see #putByte(long, byte) */public native void putDouble(long address, double x);//从已经给的一个内存地址中获取本地指针地址。public native long getAddress(long address);//把一个本地指针值x存储到内存地址address处。public native void putAddress(long address, long x);// 内存分配函方法,malloc,free等//分配一个bytes大小的内存块,返回内存地址。public native long allocateMemory(long bytes);//为内存地址为address的空间重新分配大小为bytes的地址。public native long reallocateMemory(long address, long bytes);//把o的偏移地址为offset的值处内存,分配bytes大小内存空间,并设值为value。public native void setMemory(Object o, long offset, long bytes, byte value);//把绝对地址为offset的值处内存,分配bytes大小内存空间,并设值为valuepublic void setMemory(long address, long bytes, byte value) {setMemory(null, address, bytes, value);}//将源object的srcoffset偏移地址处的bytes大小内存,放入destBase偏移地址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);}//释放地址为address初的内存。public native void freeMemory(long address);// / random queries,随机查询。//错误地址public static final int INVALID_FIELD_OFFSET = -1;//获取静态变量f的内存地址public native long staticFieldOffset(Field f);//获取普通变量f的内存地址。public native long objectFieldOffset(Field f);//获取静态变量f的内存地址。public native Object staticFieldBase(Field f);//检测,当前class c是否应该被初始化,public native boolean shouldBeInitialized(Class<?> c);//保证当前class c 已经被初始化了。public native void ensureClassInitialized(Class<?> c);//返回arrayClass类第一个字节的地址。public native int arrayBaseOffset(Class<?> arrayClass);/** The value of {@code arrayBaseOffset(boolean[].class)} */public static final int ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe.arrayBaseOffset(boolean[].class);/** The value of {@code arrayBaseOffset(byte[].class)} */public static final int ARRAY_BYTE_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);/** The value of {@code arrayBaseOffset(short[].class)} */public static final int ARRAY_SHORT_BASE_OFFSET = theUnsafe.arrayBaseOffset(short[].class);/** The value of {@code arrayBaseOffset(char[].class)} */public static final int ARRAY_CHAR_BASE_OFFSET = theUnsafe.arrayBaseOffset(char[].class);/** The value of {@code arrayBaseOffset(int[].class)} */public static final int ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset(int[].class);/** The value of {@code arrayBaseOffset(long[].class)} */public static final int ARRAY_LONG_BASE_OFFSET = theUnsafe.arrayBaseOffset(long[].class);/** The value of {@code arrayBaseOffset(float[].class)} */public static final int ARRAY_FLOAT_BASE_OFFSET = theUnsafe.arrayBaseOffset(float[].class);/** The value of {@code arrayBaseOffset(double[].class)} */public static final int ARRAY_DOUBLE_BASE_OFFSET = theUnsafe.arrayBaseOffset(double[].class);/** The value of {@code arrayBaseOffset(Object[].class)} */public static final int ARRAY_OBJECT_BASE_OFFSET = theUnsafe.arrayBaseOffset(Object[].class);//返回数组元素的大小,注意byte类型获取则为0public native int arrayIndexScale(Class<?> arrayClass);/** The value of {@code arrayIndexScale(boolean[].class)} */public static final int ARRAY_BOOLEAN_INDEX_SCALE = theUnsafe.arrayIndexScale(boolean[].class);/** The value of {@code arrayIndexScale(byte[].class)} */public static final int ARRAY_BYTE_INDEX_SCALE = theUnsafe.arrayIndexScale(byte[].class);/** The value of {@code arrayIndexScale(short[].class)} */public static final int ARRAY_SHORT_INDEX_SCALE = theUnsafe.arrayIndexScale(short[].class);/** The value of {@code arrayIndexScale(char[].class)} */public static final int ARRAY_CHAR_INDEX_SCALE = theUnsafe.arrayIndexScale(char[].class);/** The value of {@code arrayIndexScale(int[].class)} */public static final int ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale(int[].class);/** The value of {@code arrayIndexScale(long[].class)} */public static final int ARRAY_LONG_INDEX_SCALE = theUnsafe.arrayIndexScale(long[].class);/** The value of {@code arrayIndexScale(float[].class)} */public static final int ARRAY_FLOAT_INDEX_SCALE = theUnsafe.arrayIndexScale(float[].class);/** The value of {@code arrayIndexScale(double[].class)} */public static final int ARRAY_DOUBLE_INDEX_SCALE = theUnsafe.arrayIndexScale(double[].class);/** The value of {@code arrayIndexScale(Object[].class)} */public static final int ARRAY_OBJECT_INDEX_SCALE = theUnsafe.arrayIndexScale(Object[].class);//返回内存大小的单位。public native int addressSize();/** The value of {@code addressSize()} */public static final int ADDRESS_SIZE = theUnsafe.addressSize();// 返回内存页的大小public native int pageSize();// / random trusted operations from JNI://告诉vm在具体内存地址定义一个类public native Class<?> defineClass(String name, byte[] b, int off, int len,ClassLoader loader, ProtectionDomain protectionDomain);//要vm去定义一个匿名类public native Class<?> defineAnonymousClass(Class<?> hostClass,byte[] data, Object[] cpPatches);//给cls类分配一个实例内存地址,而不掉用构造器public native Object allocateInstance(Class<?> cls)throws InstantiationException;//抛出错误。并不会通知verifierpublic native void throwException(Throwable ee);//原子性的更新java变量public final native boolean compareAndSwapObject(Object o, long offset,Object expected, Object x);/*** Atomically update Java variable to <tt>x</tt> if it is currently holding* <tt>expected</tt>.* * @return <tt>true</tt> if successful*/public final native boolean compareAndSwapInt(Object o, long offset,int expected, int x);/*** Atomically update Java variable to <tt>x</tt> if it is currently holding* <tt>expected</tt>.* * @return <tt>true</tt> if successful*/public final native boolean compareAndSwapLong(Object o, long offset,long expected, long x);//在o的offset偏移地址处,获取volatile类型的对象public native Object getObjectVolatile(Object o, long offset);/*** Stores a reference value into a given Java variable, with volatile store* semantics. Otherwise identical to* {@link #putObject(Object, long, Object)}*/public native void putObjectVolatile(Object o, long offset, Object x);/** Volatile version of {@link #getInt(Object, long)} */public native int getIntVolatile(Object o, long offset);/** Volatile version of {@link #putInt(Object, long, int)} */public native void putIntVolatile(Object o, long offset, int x);/** Volatile version of {@link #getBoolean(Object, long)} */public native boolean getBooleanVolatile(Object o, long offset);/** Volatile version of {@link #putBoolean(Object, long, boolean)} */public native void putBooleanVolatile(Object o, long offset, boolean x);/** Volatile version of {@link #getByte(Object, long)} */public native byte getByteVolatile(Object o, long offset);/** Volatile version of {@link #putByte(Object, long, byte)} */public native void putByteVolatile(Object o, long offset, byte x);/** Volatile version of {@link #getShort(Object, long)} */public native short getShortVolatile(Object o, long offset);/** Volatile version of {@link #putShort(Object, long, short)} */public native void putShortVolatile(Object o, long offset, short x);/** Volatile version of {@link #getChar(Object, long)} */public native char getCharVolatile(Object o, long offset);/** Volatile version of {@link #putChar(Object, long, char)} */public native void putCharVolatile(Object o, long offset, char x);/** Volatile version of {@link #getLong(Object, long)} */public native long getLongVolatile(Object o, long offset);/** Volatile version of {@link #putLong(Object, long, long)} */public native void putLongVolatile(Object o, long offset, long x);/** Volatile version of {@link #getFloat(Object, long)} */public native float getFloatVolatile(Object o, long offset);/** Volatile version of {@link #putFloat(Object, long, float)} */public native void putFloatVolatile(Object o, long offset, float x);/** Volatile version of {@link #getDouble(Object, long)} */public native double getDoubleVolatile(Object o, long offset);/** Volatile version of {@link #putDouble(Object, long, double)} */public native void putDoubleVolatile(Object o, long offset, double x);/*** @description putObjectVolatile这个方法,并不会立刻保证可见性,* lazySet是使用Unsafe.putOrderedObject方法,这个方法在对低延迟代码是很有用的,* 它能够实现非堵塞的写入,这些写入不会被Java的JIT重新排序指令(instruction reordering),* 这样它使用快速的存储-存储(store-store) barrier, 而不是较慢的存储-加载(store-load) barrier,*  后者总是用在volatile的写操作上,这种性能提升是有代价的,虽然便宜,也就是写后结果并不会被其他线程看到,*  甚至是自己的线程,通常是几纳秒后被其他线程看到,这个时间比较短,所以代价可以忍受。*  类似Unsafe.putOrderedObject还有unsafe.putOrderedLong等方法,unsafe.putOrderedLong比使用 volatile long要快3倍左右。. */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);//释放相关阻塞线程。获得信号量public native void unpark(Object thread);//阻塞相关线程块,等待信号量public native void park(boolean isAbsolute, long time);//根据给定的nelem,即loadavg查询系统负载。public native int getLoadAverage(double[] loadavg, int nelems);// The following contain CAS-based Java implementations used on// platforms not supporting native instructions//以下是原子性相关的cas操作//原子性int的自增。阻塞性的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;}原子性long的自增。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;}//原子性的设置int值,也是阻塞式的。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;}/*** Atomically exchanges the given value with the current value of a field or* array element within the given object <code>o</code> at the given* <code>offset</code>.* * @param o*            object/array to update the field/element in* @param offset*            field/element offset* @param newValue*            new value* @return the previous value* @since 1.8*/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;}/*** Atomically exchanges the given reference value with the current reference* value of a field or array element within the given object <code>o</code>* at the given <code>offset</code>.* * @param o*            object/array to update the field/element in* @param offset*            field/element offset* @param newValue*            new value* @return the previous value* @since 1.8*/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;}/*** Ensures lack of reordering of loads before the fence with loads or stores* after the fence.* @description 确保没有在写前面的重排序* @since 1.8*/public native void loadFence();/*** Ensures lack of reordering of stores before the fence with loads or* stores after the fence.* @description 确保没有读相关重排序* @since 1.8*/public native void storeFence();/*** Ensures lack of reordering of loads or stores before the fence with loads* or stores after the fence.* @description 确保读写重排序* @since 1.8*/public native void fullFence();//被vm用于抛异常private static void throwIllegalAccessError() {throw new IllegalAccessError();}
}

参考文档:
https://www.cnblogs.com/mickole/articles/3757278.html
https://stackoverflow.com/questions/23603304/java-8-unsafe-xxxfence-instructions
https://bugs.openjdk.java.net/browse/JDK-8038978
http://www.jdon.com/performance/java-performance-optimizations-queue.html

Java并发学习(四)-sun.misc.Unsafe相关推荐

  1. OpenJDK1.8 :java/lang/NoSuchMethodError‘: Method sun.misc.Unsafe.defineClass(Ljava/lang/String;[BII)

    记录一个OpenJDK1.8的一个BUG : Crash日志 报错信息 : Event: 0.078 Thread 0x00007f1160055800 Exception <a 'java/l ...

  2. 在Java 9中使用sun.misc.Unsafe

    Java 9 EA版本已经发布,现在我们可以看到如何使用sun.misc.Unsafe. 我领导了公开运动,以保留对Java 9的访问,该访问最终成功,从而导致对JEP 260的修订. 那么,事情如何 ...

  3. Java中的天使和魔鬼sun.misc.Unsafe

    我们在看ConcurrentHashMap源码时经常看到Unsafe类的使用,今天我们来了解下Unsafe类. Java是一个安全的编程语言,它能最大程度的防止程序员犯一些低级的错误(大部分是和内存管 ...

  4. JVM 的 Finalization Delay 引起的 OOM(java.lang.OutOfMemoryError:null at sun.misc.Unsafe.allocateMemory.)

    今天在压力测试环境某一个服务出现crash了,经过一番检查,终于发现是由于JVM的Finalization Delay引起的,这个问题比较特殊,这里记录一下. 这个服务是用Java写的,主要完成的功能 ...

  5. unsafe jdk9_JDK 9清单:Project Jigsaw,sun.misc.Unsafe,G1,REPL等

    unsafe jdk9 Java 9距离(希望)数月了,现在该回顾一下即将发生的变化以及您应该采取的措施 Java 9即将来临(我们正在计算到达的日子 ),其中包含一系列新功能和改进功能. 这就是为什 ...

  6. JDK 9清单:Project Jigsaw,sun.misc.Unsafe,G1,REPL等

    Java 9距离(希望)数月了,现在该讨论一下即将发生的变化以及您应该采取的措施 Java 9即将来临(我们正在计算到达的日子 ),其中包含一系列新功能和改进功能. 这就是为什么我们决定创建一份清单来 ...

  7. unsafehelper java_Java 9中将移除 Sun.misc.Unsafe

    灾难将至,Java 9中将移除 Sun.misc.Unsafe Oracle 正在计划在Java 9中去掉 sun.misc.Unsafe API. 这绝对将是一场灾难,有可能会彻底破坏整个 java ...

  8. sun.misc.Unsafe苦难告诉我们什么

    Oracle将删除Java 9中的内部sun.misc.Unsafe类 . 尽管大多数人可能对这种变化漠不关心,但其他一些人(主要是图书馆开发人员)并非如此. 博客圈中最近有几篇文章描绘了这种变化所暗 ...

  9. 深入理解sun.misc.Unsafe原理

    前言 Unsafe类在JDK源码中被广泛使用,在Spark使用off-heap memory时也会使用到,该类功能很强大,涉及到类加载机制(深入理解ClassLoader工作机制),其实例一般情况是获 ...

  10. 聊聊高并发(十七)解析java.util.concurrent各个组件(一) 了解sun.misc.Unsafe类

    了解了并发编程中锁的基本原理之后,接下来看看Java是如何利用这些原理来实现各种锁,原子变量,同步组件的.在开始分析java.util.concurrent的源代码直接,首先要了解的就是sun.mis ...

最新文章

  1. GitHub 上有哪些适合新手跟进的优质项目?(附地址)
  2. “毕业”式裁员的祖宗?
  3. java poi jar maven_使用maven引入Apache poi jar包
  4. 你所需要的java网络编程大总结
  5. powershell实现设置程序相关性脚本
  6. spring cloud每次修改必须重新打包_Java面试系列spring相关
  7. DNS服务器之二:从服务器的实现
  8. PAIP.在程序中设置壁纸墙纸
  9. 黑页网站html源码,仿360网站卫士拦截页面黑页源码
  10. matlab二维傅里叶变化并得到频谱,图像的二维傅里叶变换和频谱
  11. java中 implement_java中implement
  12. WordStream:谷歌广告各指标分析
  13. 用“狗屁不通文章生成器”写作文,竟打败73.5%的学生?
  14. ACP报名考试有学历限制吗?
  15. DBA职业规划技术成长路线
  16. Vue 路由懒加载——介绍以及遇到的问题
  17. 转载一位老码农的技术理想
  18. 读书笔记--项亮《推荐系统实践》第一章
  19. 跨时钟域为什么要双寄存器同步
  20. bouguet算法极线校正出现视野丢失问题(求解答)

热门文章

  1. Postgresql - cursor介绍
  2. MatrixOne混沌测试之道
  3. 2022东北四省赛 F. Tree Path (树剖 + 线段树维护堆)
  4. java 根据条件从List中筛选出符合条件的集合
  5. 飞马哥:正确推广模式框架的解析
  6. iOS开发 frame与bounds
  7. 毕业生最大感伤:穷!
  8. centos7.4源码安装nginx-1.16.1 及NGINX最全配置 缓存缩略图4层转发
  9. WordPress 安装时出现的问题
  10. SQL语句中对时间字段进行区间查询