一 介绍
- 一个管理内存的类
- 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)
方法用于保证已经初始化过一个类