浅析Unsafe类

sun.misc.Unsafe类提供了像C语言那样直接操作内存的能力,Unsafe开辟的内存空间不占用heap空间,也不被GC回收

 1 private static final Unsafe theUnsafe;
 2 
 3 private Unsafe() {
 4 }
 5 
 6 @CallerSensitive
 7 public static Unsafe getUnsafe() {
 8     Class var0 = Reflection.getCallerClass();
 9     if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
10         throw new SecurityException("Unsafe");
11     } else {
12         return theUnsafe;
13     }
14 }

直接调用getUnsafe会过不了安全性检查

 1 package yuanma;
 2 
 3 import sun.misc.Unsafe;
 4 
 5 public class Test {
 6     public static void main(String[] args) {
 7         Unsafe unsafe = Unsafe.getUnsafe();
 8     }
 9 }
10 /*
11 Exception in thread "main" java.lang.SecurityException: Unsafe
12     at sun.misc.Unsafe.getUnsafe(Unsafe.java:90)
13     at yuanma.Test.main(Test.java:7)
14  */

可以通过修改-Xbootclasspath参数或者反射来获取Unsafe实例,正确的姿势是这样的

 1 package yuanma;
 2 
 3 import sun.misc.Unsafe;
 4 
 5 import java.lang.reflect.Field;
 6 
 7 public class Test {
 8     public static void main(String[] args) {
 9         try {
10             Field f = Unsafe.class.getDeclaredField("theUnsafe");
11             f.setAccessible(true);
12             Unsafe unsafe = (Unsafe) f.get(null);
13         } catch (Exception e) {
14             e.printStackTrace();
15         }
16     }
17 }

获取到Unsafe实例之后,就真的可以为所欲为了

1. 内存管理

allocateMemory(分配内存,不被GC回收需要手动free)、reallocateMemory(重新分配内存)、copyMemory(拷贝内存)、freeMemory(释放内存)

getAddress(获取内存地址)、addressSize、pageSize、getInt(获取内存地址指向的整数)、getIntVolatile(获取内存地址指向的整数并支持volatile语义)

putInt(将整数写入指定内存地址)、putIntVolatile(将整数写入指定内存地址并支持volatile语义)、putOrderedInt(将整数写入指定内存地址,有序或者有延迟的方法)

copyMemory无需对象实现clone方法即可拷贝对象(浅拷贝)

2. 非常规的对象实例化

allocateInstance方法直接生成对象实例,无需new或者反射获取对象——对象反序列化时不需要调用构造方法,能够重建和设置final字段

 1 package yuanma;
 2 
 3 import sun.misc.Unsafe;
 4 
 5 import java.lang.reflect.Field;
 6 
 7 public class Test {
 8     public static void main(String[] args) {
 9         try {
10             Field f = Unsafe.class.getDeclaredField("theUnsafe");
11             f.setAccessible(true);
12             Unsafe unsafe = (Unsafe) f.get(null);
13             Student student = (Student) unsafe.allocateInstance(Student.class);
14             student.setName("bin");
15             System.out.println(student.getName()); // bin
16         } catch (Exception e) {
17             e.printStackTrace();
18         }
19     }
20 
21     class Student {
22         String name;
23 
24         public String getName() {
25             return name;
26         }
27 
28         public void setName(String name) {
29             this.name = name;
30         }
31     }
32 }

3. 操作类、对象及变量

staticFieldOffset(静态域偏移)、defineClass(定义类)、defineAnonymousClass(定义匿名类)、ensureClassInitialized(确保类初始化)、objectFieldOffset(对象域偏移)

可以获取对象的指针,通过对指针进行偏移,不仅可以直接修改指针指向的数据(即使是私有的),甚至可以找到JVM已经认定为垃圾,可以回收的对象

4. 数组操作

arrayBaseOffset(获取数组第一个元素的偏移地址)+arrayIndexScale(获取数组中元素的增量地址)定位数组任意元素

由于Java数组最大长度为Integer.MAX_VALUE,而用Unsafe类的内存分配方法可以实现超大数组,实际上可以认为是C数组

 1 package yuanma;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         byte[] arr = new byte[Integer.MAX_VALUE + 1];
 6     }
 7 }
 8 /*
 9 Exception in thread "main" java.lang.NegativeArraySizeException
10     at yuanma.Test.main(Test.java:5)
11  */
 1 package yuanma;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         byte[] arr = new byte[Integer.MAX_VALUE];
 6     }
 7 }
 8 /*
 9 Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
10     at yuanma.Test.main(Test.java:5)
11  */

5. 线程同步

monitorEnter、tryMonitorEnter、monitorExit、compareAndSwapInt、compareAndSwap

6. 挂起与恢复

park、unpark——整个并发框架中对线程的挂起恢复操作被封装在LockSupport类中

7. 内存屏障

loadFence、storeFence、fullFence——用于定义内存屏障,避免代码重排序

 

转载于:https://www.cnblogs.com/sakura1027/p/9504556.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值