一、Atominc 原子包

在 Atomic 包中有12个类,四种原子更新办法,分别是原子更新根本类型、数组、引证和字段。Atomic 包里的类根本都是运用 Unsafe 完成的包装类。

  • 根本类: AtomicInteger、AtomicLong、AtomicBoolean
  • 引证类型: AtomicReference、AtomicStampedRerence、AtomicMarkableReference
  • 数组类型: AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
  • 特点原子修正器(Updater): AtomicIntegerFieldUpdater、 AtomicLongFieldUpdater、AtomicReferenceFieldUpdater

什么是偏移量?

咱们运用 CAS 修正某个目标的特点值是,首先需求知道该特点在目标的内存空间的那个方位,就必须要知道目标的偏移量,经过偏移量就能直接找到这个特点。

7.Atominc 原子包及 Unsafe 魔法类
CAS无锁并发算法

7.Atominc 原子包及 Unsafe 魔法类
能够经过添加版本号解决ABA问题

1、原子更新根本类型类

  • AtomicBoolean: 原子更新布尔类型
  • AtomicInteger: 原子更新整型。
  • AtomicLong: 原子更新长整型。

以 AtomicInteger 为例部分 API 如下:

办法 用处
int addAndGet(int delta) 以原子办法将输入的数值与实例中的值 (AtomicInteger里的value)相加,并回来成果
boolean compareAndSet(int expect, int update) 如果输入的数值等于预期值,则以原子办法将该值设置为输入的值
int getAndIncrement() 以原子办法将当前值加1,留意:这儿回来的是自增
void lazySet(int newValue) 终究设置成 newValue,运用lazySet设置值后,或许导致其他线程在之后的一小段时间内还是能够读到旧的值
int getAndSet(int newValue) 以原子办法设置为newValue的值,并回来旧

部分源码分析:

// Unsafe类
/**
 * 大多API根本都是如此规划
 * @param var1 目标AtomicInteger 
 * @param var2 偏移量
 * @param var4 需求加的数值
 */
public final int getAndAddInt(Object var1, long var2, int var4) {
  int var5; // oldValue 旧值
  do {
    var5 = this.getIntVolatile(var1, var2); // 读AtomicInteger的value值
   } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
​
  return var5;
}

2、原子更新数组类

  • AtomicIntegerArray:原子更新整型数组里的元素
  • AtomicLongArray:原子更新长整型数组里的元素
  • AtomicReferenceArray:原子更新引证类型数组里的元素

以 AtomicIntegerArray为例部分 API 如下:

办法 用处
int addAndGet(int i, int delta) 以原子办法将输入值与数组中索引 i 的元素相加
boolean compareAndSet(int i, int expect, int update) 如果当前值等于预期值,则以原子办法将数组方位i的元素设置成update值

留意: 此数组并非原数组,而是浅复制(调用了 clone 办法)的一份数组

public AtomicIntegerArray(int[] array) {
  // Visibility guaranteed by final field guarantees
  this.array = array.clone();
}

3、原子更新引证类型

  • AtomicReference:原子更新引证类型
  • AtomicReferenceFieldUpdater:原子更新引证类型里的特点(字段)
  • AtomicMarkableReference:原子更新带有符号位的引证类型

4、原子更新字段类

  • AtomicIntegerFieldUpdater:原子更新整型的字段的更新器
  • AtomicLongFieldUpdater:原子更新长整型字段的更新器
  • AtomicStampedReference:原子更新带有版本号的引证类型(可解决 CAS 问题)

AtomicStampedReference 将整数值与引证关联起来,可用于原子的更数据和数据的版本号,能够解决运用 CAS 进行原子更新时,或许呈现的ABA问题。compareAndSet办法有两个参数和四个参数两种,四个参数的会传递对应的版本号,版本号在每次修正后会进行地址操作。

public class AtomicStampedReferenceRunner {
​
  private static AtomicStampedReference<Integer> atomicStampedRef =
      new AtomicStampedReference<>(1, 0);
​
  public static void main(String[] args){
    Thread main = new Thread(() -> {
      int stamp = atomicStampedRef.getStamp(); //获取当前标识别
      System.out.println("操作线程" + Thread.currentThread()+ "stamp = "+stamp + ",初始值 a = " + atomicStampedRef.getReference());
      try {
        Thread.sleep(3000); //等待3秒 ,以便让搅扰线程履行
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
      boolean isCASSuccess = atomicStampedRef.compareAndSet(1,2,stamp,stamp +1); //此时expectedReference未发生改变,可是stamp现已被修正了,所以CAS失利
      System.out.println("操作线程" + Thread.currentThread() + "stamp = "+stamp + ",CAS操作成果: " + isCASSuccess);
     },"主操作线程");
​
    Thread other = new Thread(() -> {
      int stamp = atomicStampedRef.getStamp();
      atomicStampedRef.compareAndSet(1,2,stamp,stamp+1);
      System.out.println("操作线程" + Thread.currentThread() + "stamp = "+atomicStampedRef.getStamp() +",【increment】 ,值 a = "+ atomicStampedRef.getReference());
      stamp = atomicStampedRef.getStamp();
      atomicStampedRef.compareAndSet(2,1,stamp,stamp+1);
      System.out.println("操作线程" + Thread.currentThread() + "stamp = "+atomicStampedRef.getStamp() +",【decrement】 ,值 a = "+ atomicStampedRef.getReference());
     },"搅扰线程");
​
    main.start();
    LockSupport.parkNanos(1000000);
    other.start();
   }
}
运行成果
------------------------------------------------------------
操作线程Thread[主操作线程,5,main]stamp = 0,初始值 a = 1
操作线程Thread[搅扰线程,5,main]stamp = 1,【increment】 ,值 a = 2
操作线程Thread[搅扰线程,5,main]stamp = 2,【decrement】 ,值 a = 1
操作线程Thread[主操作线程,5,main]stamp = 0,CAS操作成果: false

二、魔法类 Unsafe

位于 sun.misc 包下的一个类,主要供给一些用于履行低级别、不安全操作的办法,如 直接拜访系统内存资源自主管理内存资源等。Unsafe 运用一定要谨慎,过度、不正确运用 Unsafe 类会使得程序犯错的概率变大,变得不再安全。

Unsafe类部分源码:

private static final Unsafe theUnsafe;
// 私有构造
private Unsafe() {
}
// 单例模式
@CallerSensitive
public static Unsafe getUnsafe() {
  Class var0 = Reflection.getCallerClass();
  // 仅在引导类加载器加载时才合法,不然抛出异常
  if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
    throw new SecurityException("Unsafe");
   } else {
    return theUnsafe;
   }
}
​
static {
  // 部分代码已省掉
  theUnsafe = new Unsafe();
}

获取 UnSafe 实例的办法

办法一:

从getUnsafe办法的运用约束条件出发,经过Java命令行命令-Xbootclasspath/a把调用Unsafe相关办法的类A地点jar包途径追加到默认的bootstrap途径中,使得A被引导类加载器加载,从而经过Unsafe.getUnsafe办法安全的获取Unsafe实例。

java Xbootclasspath/a:${path} // 其间path为调用Unsafe相关办法的类地点jar包途径

办法二:

经过反射获取单例目标 theUnsafe,一般能够把它写成一个东西类

public class UnsafeInstance {
  public static Unsafe reflectGetUnsafe() {
    try {
      Field field = Unsafe.class.getDeclaredField("theUnsafe");
      field.setAccessible(true);
      return (Unsafe) field.get(null);
     } catch (Exception e) {
      e.printStackTrace();
     }
    return null;
   }
​
  public static void main(String[] args) {
    int j=1;
    reflectGetUnsafe().loadFence();
    int i= 0;
   }
}

Unsafe 用处分类

7.Atominc 原子包及 Unsafe 魔法类

1、内存操作

// 分配内存
public native long allocateMemory(long var1);
// 扩充内存
public native long reallocateMemory(long var1, long var3);
// 在给定的内存块中设置值
public native void setMemory(Object var1, long var2, long var4, byte var6);
​
public void setMemory(long var1, long var3, byte var5) {
  this.setMemory((Object)null, var1, var3, var5);
}
// 内存复制
public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);
​
public void copyMemory(long var1, long var3, long var5) {
  this.copyMemory((Object)null, var1, (Object)null, var3, var5);
}
// 开释内存
public native void freeMemory(long var1);
​
// 获取给定地址值,疏忽润饰限定符的拜访约束。与此相似操作还有: getInt, getDouble,getLong,getChar等 
public native Object getObject(Object o, long offset) 
// 为给定地址设置值,疏忽润饰限定符的拜访约束,与此相似操作还有: putInt,putDouble,putLong,putChar等 
public native void putObject(Object o, long offset, Object x) 
// 获取给定地址byte类型的值
public native byte getByte(long address) 
//为给定地址设置byte类型的值(当且仅当该内存地址为 allocateMemory 分配时,此办法成果才是确定的) 
public native void putByte(long address, byte x)

为什么要运用堆外内存?

  • 优化废物收回,堆外内存直接由操作系统管理,不受 JVM 操控,运用堆外内存能够减小堆内存压力,从而削减 GC 时削减废物收回中止对运用的影响。
  • 提高程序I/O操作的功能,一般在I/O通信过程中,会存在堆内内存到堆外内存的数据复制操作,关于需求频繁进行内存间数据复制且生命周期较短的暂存数据,都建议存储到堆外内存

留意: 堆外内存不受 JVM 操控,用完一定要进行开释

典型运用

DirectByteBuffer 是 Java 用于完成堆外内存的一个重要类,咱们能够经过该类完成堆外内存的创建、运用和销毁。

DirectByteBuffer(int cap) {          // package-private
  super(-1, 0, cap, cap);
  boolean pa = VM.isDirectMemoryPageAligned();
  int ps = Bits.pageSize();
  long size = Math.max(1L, (long)cap + (pa ? ps : 0));
  // 保留总分配内存(按页分配)的巨细和实际内存的巨细
  Bits.reserveMemory(size, cap);
​
  long base = 0;
  try {
    // 分配堆外内存,并回来堆外内存的基地址
    base = unsafe.allocateMemory(size);
   } catch (OutOfMemoryError x) {
    Bits.unreserveMemory(size, cap);
    throw x;
   }
  // 内存初始化
  unsafe.setMemory(base, size, (byte) 0);
  if (pa && (base % ps != 0)) {
    // Round up to page boundary
    address = base + ps - (base & (ps - 1));
   } else {
    address = base;
   }
  // 构建Cleaner目标用于跟踪DirectByteBuffer目标的废物收回
  // 以完成当DirectByteBuffer被废物收回时,堆外内存也会被开释
  cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
  att = null;
}
public static void main(String[] args) {
  Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
  long oneHundred = 12012341234567891234L;
  byte size = 8;
  // 调用allocateMemory分配内存
  long memoryAddress = unsafe.allocateMemory(size);
  System.out.println("address:"+memoryAddress);
  // 写入到内存中
  unsafe.putAddress(memoryAddress, oneHundred);
  // 内存中读取数据
  long readValue = unsafe.getAddress(memoryAddress);
​
  System.out.println("value:" + readValue);
    // 开释内存
  unsafe.freeMemory(memoryAddress);
}
运行成果
--------------------------------------
address:56555456
value:12012341234567891234L

2、CAS相关

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5)
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5) 
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6)

3、线程调度

//取消堵塞线程 
public native void unpark(Object thread) 
//堵塞线程 
public native void park(boolean isAbsolute, long time) 
//获得目标锁(可重入锁) 
@Deprecated 
public native void monitorEnter(Object o) 
//开释目标锁 
@Deprecated 
public native void monitorExit(Object o) 
//尝试获取目标锁 
@Deprecated 
public native boolean tryMonitorEnter(Object o)

典型运用

1.LockSupport.park()和LockSupport.unpark()完成线程的堵塞和唤醒

2.跨办法加解锁

public class ObjectMonitorRunner {
  static Object object = new Object();
  // 获取Unsafe目标
  static Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
  public void method1(){
    unsafe.monitorEnter(object); // 加锁
   }
​
  public void method2(){
    unsafe.monitorExit(object); // 开释锁
   }
}

4、内存屏障

//内存屏障,制止load操作重排序。屏障前的load操作不能被重排序到屏障后,屏障后的load操作不能被重排序到屏障前 
public native void loadFence() 
//内存屏障,制止store操作重排序。屏障前的store操作不能被重排序到屏障后,屏障后的store操作不能被重排序到屏障前
public native void storeFence() 
//内存屏障,制止load、store操作重排序 
public native void fullFence()

附 UNsafe 源码:

package sun.misc;
​
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
​
public final class Unsafe {
  private static final Unsafe theUnsafe;
  public static final int INVALID_FIELD_OFFSET = -1;
  public static final int ARRAY_BOOLEAN_BASE_OFFSET;
  public static final int ARRAY_BYTE_BASE_OFFSET;
  public static final int ARRAY_SHORT_BASE_OFFSET;
  public static final int ARRAY_CHAR_BASE_OFFSET;
  public static final int ARRAY_INT_BASE_OFFSET;
  public static final int ARRAY_LONG_BASE_OFFSET;
  public static final int ARRAY_FLOAT_BASE_OFFSET;
  public static final int ARRAY_DOUBLE_BASE_OFFSET;
  public static final int ARRAY_OBJECT_BASE_OFFSET;
  public static final int ARRAY_BOOLEAN_INDEX_SCALE;
  public static final int ARRAY_BYTE_INDEX_SCALE;
  public static final int ARRAY_SHORT_INDEX_SCALE;
  public static final int ARRAY_CHAR_INDEX_SCALE;
  public static final int ARRAY_INT_INDEX_SCALE;
  public static final int ARRAY_LONG_INDEX_SCALE;
  public static final int ARRAY_FLOAT_INDEX_SCALE;
  public static final int ARRAY_DOUBLE_INDEX_SCALE;
  public static final int ARRAY_OBJECT_INDEX_SCALE;
  public static final int ADDRESS_SIZE;
​
  private static native void registerNatives();
​
  private Unsafe() {
   }
​
  @CallerSensitive
  public static Unsafe getUnsafe() {
    Class var0 = Reflection.getCallerClass();
    if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
      throw new SecurityException("Unsafe");
     } else {
      return theUnsafe;
     }
   }
​
  public native int getInt(Object var1, long var2);
​
  public native void putInt(Object var1, long var2, int var4);
​
  public native Object getObject(Object var1, long var2);
​
  public native void putObject(Object var1, long var2, Object var4);
​
  public native boolean getBoolean(Object var1, long var2);
​
  public native void putBoolean(Object var1, long var2, boolean var4);
​
  public native byte getByte(Object var1, long var2);
​
  public native void putByte(Object var1, long var2, byte var4);
​
  public native short getShort(Object var1, long var2);
​
  public native void putShort(Object var1, long var2, short var4);
​
  public native char getChar(Object var1, long var2);
​
  public native void putChar(Object var1, long var2, char var4);
​
  public native long getLong(Object var1, long var2);
​
  public native void putLong(Object var1, long var2, long var4);
​
  public native float getFloat(Object var1, long var2);
​
  public native void putFloat(Object var1, long var2, float var4);
​
  public native double getDouble(Object var1, long var2);
​
  public native void putDouble(Object var1, long var2, double var4);
​
  /** @deprecated */
  @Deprecated
  public int getInt(Object var1, int var2) {
    return this.getInt(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putInt(Object var1, int var2, int var3) {
    this.putInt(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public Object getObject(Object var1, int var2) {
    return this.getObject(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putObject(Object var1, int var2, Object var3) {
    this.putObject(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public boolean getBoolean(Object var1, int var2) {
    return this.getBoolean(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putBoolean(Object var1, int var2, boolean var3) {
    this.putBoolean(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public byte getByte(Object var1, int var2) {
    return this.getByte(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putByte(Object var1, int var2, byte var3) {
    this.putByte(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public short getShort(Object var1, int var2) {
    return this.getShort(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putShort(Object var1, int var2, short var3) {
    this.putShort(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public char getChar(Object var1, int var2) {
    return this.getChar(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putChar(Object var1, int var2, char var3) {
    this.putChar(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public long getLong(Object var1, int var2) {
    return this.getLong(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putLong(Object var1, int var2, long var3) {
    this.putLong(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public float getFloat(Object var1, int var2) {
    return this.getFloat(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putFloat(Object var1, int var2, float var3) {
    this.putFloat(var1, (long)var2, var3);
   }
​
  /** @deprecated */
  @Deprecated
  public double getDouble(Object var1, int var2) {
    return this.getDouble(var1, (long)var2);
   }
​
  /** @deprecated */
  @Deprecated
  public void putDouble(Object var1, int var2, double var3) {
    this.putDouble(var1, (long)var2, var3);
   }
​
  public native byte getByte(long var1);
​
  public native void putByte(long var1, byte var3);
​
  public native short getShort(long var1);
​
  public native void putShort(long var1, short var3);
​
  public native char getChar(long var1);
​
  public native void putChar(long var1, char var3);
​
  public native int getInt(long var1);
​
  public native void putInt(long var1, int var3);
​
  public native long getLong(long var1);
​
  public native void putLong(long var1, long var3);
​
  public native float getFloat(long var1);
​
  public native void putFloat(long var1, float var3);
​
  public native double getDouble(long var1);
​
  public native void putDouble(long var1, double var3);
​
  public native long getAddress(long var1);
​
  public native void putAddress(long var1, long var3);
​
  public native long allocateMemory(long var1);
​
  public native long reallocateMemory(long var1, long var3);
​
  public native void setMemory(Object var1, long var2, long var4, byte var6);
​
  public void setMemory(long var1, long var3, byte var5) {
    this.setMemory((Object)null, var1, var3, var5);
   }
​
  public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);
​
  public void copyMemory(long var1, long var3, long var5) {
    this.copyMemory((Object)null, var1, (Object)null, var3, var5);
   }
​
  public native void freeMemory(long var1);
​
  /** @deprecated */
  @Deprecated
  public int fieldOffset(Field var1) {
    return Modifier.isStatic(var1.getModifiers()) ? (int)this.staticFieldOffset(var1) : (int)this.objectFieldOffset(var1);
   }
​
  /** @deprecated */
  @Deprecated
  public Object staticFieldBase(Class<?> var1) {
    Field[] var2 = var1.getDeclaredFields();
​
    for(int var3 = 0; var3 < var2.length; ++var3) {
      if (Modifier.isStatic(var2[var3].getModifiers())) {
        return this.staticFieldBase(var2[var3]);
       }
     }
​
    return null;
   }
​
  public native long staticFieldOffset(Field var1);
​
  public native long objectFieldOffset(Field var1);
​
  public native Object staticFieldBase(Field var1);
​
  public native boolean shouldBeInitialized(Class<?> var1);
​
  public native void ensureClassInitialized(Class<?> var1);
​
  public native int arrayBaseOffset(Class<?> var1);
​
  public native int arrayIndexScale(Class<?> var1);
​
  public native int addressSize();
​
  public native int pageSize();
​
  public native Class<?> defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);
​
  public native Class<?> defineAnonymousClass(Class<?> var1, byte[] var2, Object[] var3);
​
  public native Object allocateInstance(Class<?> var1) throws InstantiationException;
​
  /** @deprecated */
  @Deprecated
  public native void monitorEnter(Object var1);
​
  /** @deprecated */
  @Deprecated
  public native void monitorExit(Object var1);
​
  /** @deprecated */
  @Deprecated
  public native boolean tryMonitorEnter(Object var1);
​
  public native void throwException(Throwable var1);
​
  public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
​
  public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
​
  public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
​
  public native Object getObjectVolatile(Object var1, long var2);
​
  public native void putObjectVolatile(Object var1, long var2, Object var4);
​
  public native int getIntVolatile(Object var1, long var2);
​
  public native void putIntVolatile(Object var1, long var2, int var4);
​
  public native boolean getBooleanVolatile(Object var1, long var2);
​
  public native void putBooleanVolatile(Object var1, long var2, boolean var4);
​
  public native byte getByteVolatile(Object var1, long var2);
​
  public native void putByteVolatile(Object var1, long var2, byte var4);
​
  public native short getShortVolatile(Object var1, long var2);
​
  public native void putShortVolatile(Object var1, long var2, short var4);
​
  public native char getCharVolatile(Object var1, long var2);
​
  public native void putCharVolatile(Object var1, long var2, char var4);
​
  public native long getLongVolatile(Object var1, long var2);
​
  public native void putLongVolatile(Object var1, long var2, long var4);
​
  public native float getFloatVolatile(Object var1, long var2);
​
  public native void putFloatVolatile(Object var1, long var2, float var4);
​
  public native double getDoubleVolatile(Object var1, long var2);
​
  public native void putDoubleVolatile(Object var1, long var2, double var4);
​
  public native void putOrderedObject(Object var1, long var2, Object var4);
​
  public native void putOrderedInt(Object var1, long var2, int var4);
​
  public native void putOrderedLong(Object var1, long var2, long var4);
​
  public native void unpark(Object var1);
​
  public native void park(boolean var1, long var2);
​
  public native int getLoadAverage(double[] var1, int var2);
​
  public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
      var5 = this.getIntVolatile(var1, var2);
     } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
​
    return var5;
   }
​
  public final long getAndAddLong(Object var1, long var2, long var4) {
    long var6;
    do {
      var6 = this.getLongVolatile(var1, var2);
     } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));
​
    return var6;
   }
​
  public final int getAndSetInt(Object var1, long var2, int var4) {
    int var5;
    do {
      var5 = this.getIntVolatile(var1, var2);
     } while(!this.compareAndSwapInt(var1, var2, var5, var4));
​
    return var5;
   }
​
  public final long getAndSetLong(Object var1, long var2, long var4) {
    long var6;
    do {
      var6 = this.getLongVolatile(var1, var2);
     } while(!this.compareAndSwapLong(var1, var2, var6, var4));
​
    return var6;
   }
​
  public final Object getAndSetObject(Object var1, long var2, Object var4) {
    Object var5;
    do {
      var5 = this.getObjectVolatile(var1, var2);
     } while(!this.compareAndSwapObject(var1, var2, var5, var4));
​
    return var5;
   }
​
  public native void loadFence();
​
  public native void storeFence();
​
  public native void fullFence();
​
  private static void throwIllegalAccessError() {
    throw new IllegalAccessError();
   }
​
  static {
    registerNatives();
    Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});
    theUnsafe = new Unsafe();
    ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe.arrayBaseOffset(boolean[].class);
    ARRAY_BYTE_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
    ARRAY_SHORT_BASE_OFFSET = theUnsafe.arrayBaseOffset(short[].class);
    ARRAY_CHAR_BASE_OFFSET = theUnsafe.arrayBaseOffset(char[].class);
    ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset(int[].class);
    ARRAY_LONG_BASE_OFFSET = theUnsafe.arrayBaseOffset(long[].class);
    ARRAY_FLOAT_BASE_OFFSET = theUnsafe.arrayBaseOffset(float[].class);
    ARRAY_DOUBLE_BASE_OFFSET = theUnsafe.arrayBaseOffset(double[].class);
    ARRAY_OBJECT_BASE_OFFSET = theUnsafe.arrayBaseOffset(Object[].class);
    ARRAY_BOOLEAN_INDEX_SCALE = theUnsafe.arrayIndexScale(boolean[].class);
    ARRAY_BYTE_INDEX_SCALE = theUnsafe.arrayIndexScale(byte[].class);
    ARRAY_SHORT_INDEX_SCALE = theUnsafe.arrayIndexScale(short[].class);
    ARRAY_CHAR_INDEX_SCALE = theUnsafe.arrayIndexScale(char[].class);
    ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale(int[].class);
    ARRAY_LONG_INDEX_SCALE = theUnsafe.arrayIndexScale(long[].class);
    ARRAY_FLOAT_INDEX_SCALE = theUnsafe.arrayIndexScale(float[].class);
    ARRAY_DOUBLE_INDEX_SCALE = theUnsafe.arrayIndexScale(double[].class);
    ARRAY_OBJECT_INDEX_SCALE = theUnsafe.arrayIndexScale(Object[].class);
    ADDRESS_SIZE = theUnsafe.addressSize();
   }
}
​