一 介紹
- 一個管理內存的類
- Unsafe類是"final"的,不允許繼承。且構造函數是private的
- 使用單列模式模式獲取類對象
1.1 測試的類
public class UnsafeBean {
private static int staticInt = 5;
private final int finalInt = 5;
}
二 代碼
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;
//final修飾,該類不能被繼承
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,不能new 構造
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;
public native void monitorEnter(Object var1);
public native void monitorExit(Object var1);
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();
}
}
三 方法
1 線程調度
1. public native void unpark(Object var1) :恢復被掛起的線程
1. var1:被掛起的線程
2. public native void park(boolean var1, long var2) :掛起當前線程
1. var1:boolean 類型,表示掛起時間的單位,true表示毫秒,false表示納秒。
2. var2:掛起多少時間,var2爲0表示永不過期
3. 阻塞一個線程直到unpark被調用或者線程被中斷或者timeout時間到期。
@Test
public void parkOrUnpark() throws InterruptedException {
Thread packThread = new Thread(() -> {
long startTime = System.currentTimeMillis();
//納秒,定義3秒堵塞時間
unsafe.park(false,3000000000L);
System.out.println("堵塞時間 :"+(System.currentTimeMillis()-startTime)+"毫秒");
});
packThread.start();
//堵塞1秒
TimeUnit.SECONDS.sleep(1);
//註釋掉下一行後,線程3秒數後進行輸出,否則在1秒後輸出
unsafe.unpark(packThread);//解除packThread的堵塞狀態
//堵塞時間 :1000毫秒
}
3public native void monitorEnter(Object o):鎖定對象,必須是沒有被鎖的
4public native void monitorExit(Object o):解鎖對象
5public native boolean tryMonitorEnter(Object o):試圖鎖定對象,返回true或false是否鎖定成功,如果鎖定,必須用monitorExit解鎖
@Test
public void monitorEnterOrmonitorExit() throws InterruptedException {
UnSafeBean unSafeBean = new UnSafeBean();
unSafeBean.setAge(20);
//鎖定對象
unsafe.monitorEnter(unSafeBean);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
//鎖定對象後,線程堵塞在這裏,只有釋放鎖纔可以設置值
//試圖鎖定對象,返回true或false是否鎖定成功
while (!unsafe.tryMonitorEnter(unSafeBean)) {
}
System.out.println("tryMonitorEnter:" + unsafe.tryMonitorEnter(unSafeBean));
//只有釋放鎖纔可以設置值
unSafeBean.setAge(100);
System.out.println("解鎖對象後age值:" + unSafeBean.getAge());
}
});
thread1.start();
Thread.sleep(2 * 1000);
System.out.println("鎖定對象後age值:" + unSafeBean.getAge());
//解鎖對象
unsafe.monitorExit(unSafeBean);
// 鎖定對象後age值:20
// tryMonitorEnter:true
// 解鎖對象後age值:100
}
---------------------------------------------------------
public class UnSafeBean {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
2 CAS相關:比較及替換值
2.1 compareAndSwapXXX(Object var1, long var2, XXX var4, XXX var5)
-
參數1:被替換的對象
-
參數2:爲值的內存地址
-
參數3:變量的預期值
-
參數4:變量要換的值
-
如果變量(參數1)目前的值等於預期值(參數3),則會將變量(參數1)的值換成新值(參數4),返回 true,如果不等於預期,則不會改變,並返回 false
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); ---------------------------- @Test public void CAS() throws NoSuchFieldException { //創建一個 Integer 對象,value 爲 1 Integer i = 1; //獲取到內部變量 value,這個變量用於存放值 Field valueField = Integer.class.getDeclaredField("value"); valueField.setAccessible(true); //獲取到內存地址 long valueAddress = unsafe.objectFieldOffset(valueField); //參數1:被替換的對象 //參數2:爲值的內存地址 //參數3:變量的預期值 //參數4:變量要換的值 //如果變量(參數1)目前的值等於預期值(參數3),則會將變量(參數1)的值換成新值(參數4),返回 true //如果不等於預期,則不會改變,並返回 false boolean isOk = unsafe.compareAndSwapInt(i,valueAddress,1,5); System.out.println("isOk:"+isOk+",i=: "+i); //isOk:true,i=: 5 i=unsafe.getIntVolatile(Integer.class,valueAddress); isOk = unsafe.compareAndSwapInt(i,valueAddress,1,5); System.out.println("isOk:"+isOk+",i=: "+i); //isOk:false,i=: 0 }
3 直接內存操作
3.1 public native long allocateMemory(long var1);
-
var1:申請的內存的大小,單位爲 byte
-
返回這塊內存的long 類型地址
@Test public void allocateMemory() { //申請8字節的內存 //返回當前申請內存的地址 long memoryAddress = unsafe.allocateMemory(8); System.out.println("memoryAddress: "+memoryAddress); //memoryAddress: 534459264 }
3.2 public native void freeMemory(long var1);
-
釋放var1地址對應的內存
-
Unsafe 申請的內存不在jvm管轄範圍內,需要手動釋放
-
生產中儘量在finally區域裏進行內存的釋放操作。
@Test public void freeMemory() { //釋放var1地址對應的內存 //Unsafe 申請的內存不在jvm管轄範圍內,需要手動釋放 //生產中儘量在finally區域裏進行內存的釋放操作。 unsafe.freeMemory(534459264L); }
3.3 public native long reallocateMemory(long var1, long var3)
-
此方法會釋放var1內存地址的內存,然後重新申請一塊var3大小的內存,並返回新的內存地址
-
如果之前那塊內存上已經存在對象了,會被拷貝到新的內存上
-
考慮:如果新內存大小小於舊內存大小會怎麼樣呢?
@Test public void reallocateMemory() { //此方法會釋放var1內存地址的內存,然後重新申請一塊var3大小的內存,並返回新的內存地址 //如果之前那塊內存上已經存在對象了,會被拷貝到新的內存上 //考慮:如果新內存大小小於舊內存大小會怎麼樣呢? long memoryAddress = unsafe.allocateMemory(8); long newMemoryAddress = unsafe.reallocateMemory(memoryAddress, 1); System.out.println("memoryAddress: "+memoryAddress); System.out.println("newMemoryAddress: "+newMemoryAddress); //memoryAddress: 544816560 //newMemoryAddress: 536527360 }
3.4 public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);內存複製
-
srcBase:源數據
-
srcOffset:源內存地址
-
destBase:目的數據
-
destOffset:目的地址
-
bytes:複製大小
@Test public void copyMemory() throws NoSuchFieldException { //分配100字節內存 返回初始地址 long address = unsafe.allocateMemory(100); //往分配的內存地址寫入值 unsafe.putInt(address, 55); //打印 System.out.println("address:"+unsafe.getInt(address)); //分配100字節內存 返回初始地址 long address1 = unsafe.allocateMemory(100); //內存複製,將內存地址address複製到內存地址address1中,複製大小爲8個字節 unsafe.copyMemory(null,address, null,address1, 8); System.out.println("address1:"+unsafe.getInt(address1));
// address:55
// address1:55
}
3.5 public native void setMemory(long var1, long var3, byte var5);將內存塊中的所有字節設置爲固定值
-
var1:被操作的對象
-
var2:被操作對象的內存地址
-
var4,var6:2個參數一起決定固定值大小
@Test public void setMemory() { //分配一個8byte的內存 long address = unsafe.allocateMemory(8L); // //將內存塊中的所有字節設置爲固定值,初始化內存填充值爲1 unsafe.setMemory(null,address, 1L, (byte) 1); //獲取內存地址對應的值 System.out.println("address value1:" + unsafe.getInt(address)); unsafe.setMemory(null,address, 2L, (byte) 1); //獲取內存地址對應的值 System.out.println("address value2:" + unsafe.getInt(address)); unsafe.setMemory(null,address, 3L, (byte) 1); //獲取內存地址對應的值 System.out.println("address value3:" + unsafe.getInt(address)); } //address value1:1 //address value2:257 //address value3:65793
4 普通讀寫
4.1直接在一個地址上讀寫
####4.1.1 getXXX(long var1):獲取var1內存地址的值
####4.1.2 putXXX(long var1, byte var3):在var1的內存地址設置值爲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);
-------------------------
@Test
public void getOrPutInt() {
//申請4字節的內存
long memoryAddress = unsafe.allocateMemory(4);
//將5存入到指定的內存地址中
unsafe.putInt(memoryAddress,5);
//根據內存地址獲取到整數
int a = unsafe.getInt(memoryAddress);
System.out.println("a: "+a);
//a: 5
}
4.2 Object屬性的讀寫
4.2.1 getXXX(Object var1, long var2):獲取指定對象var1的指定內存地址var2對應的值
4.2.2 putXXX(Object var1, long var2, int var4):修改指定對象var1的指定內存地址var2對應的值
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);
-------------------------
@Test
public void getOrPutInt2() throws NoSuchFieldException {
//先通過變量名反射獲取到該變量
Field staticIntField = UnsafeBean.class.getDeclaredField("staticInt");
//無視權限
staticIntField.setAccessible(true);
//夠獲取到類中的 static 修飾的變量
long staticIntAddress = unsafe.staticFieldOffset(staticIntField);
//修改指定對象的指定內存地址對應的值
unsafe.putInt(UnsafeBean.class,staticIntAddress,10);
//獲取指定對象的指定內存地址對應的值
int stiatcIntTest = unsafe.getInt(UnsafeBean.class,staticIntAddress);
//此處輸出爲 10
System.out.println("stiatcIntTest:"+stiatcIntTest);
//stiatcIntTest:10
}
5 偏移量相關
-
staticFieldOffset(Field var1):獲取靜態字段在對象實例中內存地址值
-
objectFieldOffset(Field var1):獲取非靜態字段在對象實例中的內存地址值
public native long staticFieldOffset(Field var1); public native long objectFieldOffset(Field var1); ----------------------------- @Test public void getXXXFieldOffset() throws NoSuchFieldException { //先通過變量名反射獲取到該變量 Field staticIntField = UnsafeBean.class.getDeclaredField("staticInt"); //無視權限 staticIntField.setAccessible(true); //獲取到類中的 static 修飾的變量的地址值 long staticIntAddress = unsafe.staticFieldOffset(staticIntField); System.out.println("staticIntAddress:"+staticIntAddress); //staticIntAddress:96 //獲取finnal修飾的變量 Field finalIntField = UnsafeBean.class.getDeclaredField("finalInt"); finalIntField.setAccessible(true); long finalIntAddress = unsafe.objectFieldOffset(finalIntField); System.out.println("finalIntAddress:"+finalIntAddress); //finalIntAddress:12 }
-
public native Object staticFieldBase(Field var1):用於返回Field所在的對象
@Test public void staticFieldBase() throws NoSuchFieldException { //先通過變量名反射獲取到該變量 Field staticIntField = UnsafeBean.class.getDeclaredField("staticInt"); //無視權限 staticIntField.setAccessible(true); //獲取Field所在的對象 Object o = unsafe.staticFieldBase(staticIntField); System.out.println("Object:"+o.toString()); //Object:class com.feizhou.example.demo.UnsafeBean }
-
arrayBaseOffset:返回一個數組第一個元素的內存地址
-
arrayIndexScale:數組中第一個元素所佔用的內存空間大小。
@Test public void arrayBaseOffsetOrArrayIndexScale() { String[] strings = new String[]{"1", "2", "3"}; //這個方法是返回一個數組第一個元素的內存地址 long i = unsafe.arrayBaseOffset(String[].class); System.out.println("數組第一個元素的內存地址 :" + i); //every index scale //數組中第一個元素所佔用的內存空間大小。也就是每個元素分配的內存空間大小 long scale = unsafe.arrayIndexScale(String[].class); System.out.println("數組中第一個元素所佔用的內存空間大小 :" + scale); //print first string in strings[] System.out.println("第一個元素 :" + unsafe.getObject(strings, i)); //第一個元素設置爲100 unsafe.putObject(strings, i + scale * 0, "100"); System.out.println("第1個元素 : :" + unsafe.getObject(strings, i + scale * 0)); System.out.println("第2個元素 : :" + unsafe.getObject(strings, i + scale * 1)); System.out.println("第3個元素 : :" + unsafe.getObject(strings, i + scale * 2)); // 數組第一個元素的內存地址 :16 // 數組中第一個元素所佔用的內存空間 :4 // 第一個元素 :1 // 第1個元素 : :100 // 第2個元素 : :2 // 第3個元素 : :3 }
6 volatile讀寫:可以保證可見性和有序性。
-
getXXXVolatile(Object var1, long var2):用於在對象var1指定偏移地址處var2,volatile讀取一個值
-
putXXXVolatile(Object var1, long var2, XXX var4):在對象var1指定偏移地址處var2,volatile寫入一個值var4
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); ------------------------- @Test public void getOrPutIntVolatile() throws NoSuchFieldException { //先通過變量名反射獲取到該變量 Field staticIntField = UnsafeBean.class.getDeclaredField("staticInt"); //無視權限 staticIntField.setAccessible(true); //獲取到類中 static修飾的變量的地址值 long staticIntAddress = unsafe.staticFieldOffset(staticIntField); //修改指定對象的指定內存地址對應的值 unsafe.putIntVolatile(UnsafeBean.class,staticIntAddress,10); //獲取指定對象的指定內存地址對應的值 int stiatcIntTest = unsafe.getIntVolatile(UnsafeBean.class,staticIntAddress); //此處輸出爲 10 System.out.println("stiatcIntTest:"+stiatcIntTest); //stiatcIntTest:10 }
7 有序寫入:保證寫入的有序性,不保證可見性
-
putOrderedXXX(Object var1, long var2, XXX var4):在對象var1指定偏移地址處var2,有序寫入一個值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); ------------------------------- @Test public void putOrderedXXX() throws NoSuchFieldException { Integer i = 1; //獲取到內部變量 value,這個變量用於存放值 Field valueField = Integer.class.getDeclaredField("value"); //無視權限 valueField.setAccessible(true); //獲取到內存地址 long valueAddress = unsafe.objectFieldOffset(valueField); ////將5存入到指定地址中 unsafe.putOrderedInt(Integer.class,valueAddress,5); //根據地址獲取到整數 int a = unsafe.getIntVolatile(Integer.class,valueAddress); System.out.println("a: "+a); //a: 5 }
8 線程調度
1public native void monitorEnter(Object o):鎖定對象,必須是沒有被鎖的
2public native void monitorExit(Object o):解鎖對象
3public native boolean tryMonitorEnter(Object o):試圖鎖定對象,返回true或false是否鎖定成功,如果鎖定,必須用monitorExit解鎖
@Test
public void monitorEnterOrmonitorExit() throws InterruptedException {
UnSafeBean unSafeBean = new UnSafeBean();
unSafeBean.setAge(20);
//鎖定對象
unsafe.monitorEnter(unSafeBean);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
//鎖定對象後,線程堵塞在這裏,只有釋放鎖纔可以設置值
//試圖鎖定對象,返回true或false是否鎖定成功
while (!unsafe.tryMonitorEnter(unSafeBean)) {
}
System.out.println("tryMonitorEnter:" + unsafe.tryMonitorEnter(unSafeBean));
//只有釋放鎖纔可以設置值
unSafeBean.setAge(100);
System.out.println("解鎖對象後age值:" + unSafeBean.getAge());
}
});
thread1.start();
Thread.sleep(2 * 1000);
System.out.println("鎖定對象後age值:" + unSafeBean.getAge());
//解鎖對象
unsafe.monitorExit(unSafeBean);
// 鎖定對象後age值:20
// tryMonitorEnter:true
// 解鎖對象後age值:100
}
---------------------------------------------------------
public class UnSafeBean {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
9 內存屏障相關
1 public native void loadFence():保證在這個屏障之前的所有讀操作都已經完成
2 public native void storeFence():保證在這個屏障之前的所有寫操作都已經完成。
3 public native void fullFence():保證在這個屏障之前的所有讀寫操作都已經完成。
10類加載
1 public native Class<?> defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6)
定義一個類,用於動態地創建類。
2 public native Class<?> defineAnonymousClass(Class<?> var1, byte[] var2, Object[] var3)
用於動態的創建一個匿名內部類。
3 public native Object allocateInstance(Class<?> var1) throws InstantiationException
方法用於創建一個類的實例,但是不會調用這個實例的構造方法,如果這個類還未被初始化,則初始化這個類。
4 public native boolean shouldBeInitialized(Class<?> var1)
方法用於判斷是否需要初始化一個類
5 public native void ensureClassInitialized(Class<?> var1)
方法用於保證已經初始化過一個類