sun.misc.Unsafe简介

本文详细介绍了Java中的sun.misc.Unsafe类,包括获取实例、实例化类、修改私有属性、抛出异常、内存Off-Heap管理、CompareAndSwap操作以及park/unpark线程控制。Unsafe提供底层编程能力,允许不通过构造函数实例化类,修改私有属性,实现原子操作,以及在堆外内存分配等,是并发和优化的重要工具。
摘要由CSDN通过智能技术生成

sun.misc.Unsafe简介

1 概要

sun.misc.Unsafe是JDK提供的用于很底层编程的类,位于sun.misc包中。在有些底层编程的场景,Java语言层面办不到的事情,我们可能需要使用JNI,借助C语言去实现。但是使用JNI并不是唯一的选择,使用JNI会将代码绑定到特定的平台,使用Unsafe类可以保留Java语言代码对平台的独立性,又实现底层编程。

2 获取Unsafe类的实例

Unsafe类并没有public的构造函数,只提供了一个静态工厂方法,这个静态方法还只提供给JDK标准库自身的类调用,在我们自己随便建的一个普通的类调用这个静态工厂方法还会抛异常。

这个静态工厂方法的代码如下:

@CallerSensitive
public static Unsafe getUnsafe() {
    Class<?> caller = Reflection.getCallerClass();
    if (!VM.isSystemDomainLoader(caller.getClassLoader()))
        throw new SecurityException("Unsafe");
    return theUnsafe;
}

可以看到,这个方法对调用者做了判断,一般的调用者调用这个方法会抛异常。

我们做个实验,编写如下代码:

import sun.misc.Unsafe;

public class TestUnsafe {

    public static Unsafe getUnsafe() {
        return Unsafe.getUnsafe();
    }

    public static void main(String[] args) {
        getUnsafe();
    }

}

编译后执行,可以看到程序抛出异常:

zk@zk-mbp:~ » java TestUnsafe
Exception in thread "main" java.lang.SecurityException: Unsafe
	at jdk.unsupported/sun.misc.Unsafe.getUnsafe(Unsafe.java:100)
	at TestUnsafe.getUnsafe(TestUnsafe.java:6)
	at TestUnsafe.main(TestUnsafe.java:10)

那么如何得到Unsafe实例呢?可以使用反射的方式。

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class TestUnsafe {

    private static Unsafe unsafe;

    static {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            unsafe = (Unsafe) f.get(null);
        } catch (Exception e) {
            //
        }
    }

}

下文将在上面的类的基础上实现几个测试Unsafe的方法。

3 使用Unsafe实例化类

看如下一个非常简单的类:

class Num {
    private int value;
    
    public Num() {
        this.value = 1;
    }
    
    public int getValue() {
        return this.value
    }
}

一个简单的Num类,有一个私有的int类型的value属性,它有get方法,没有set方法,在唯一的构造函数中给value赋值为1

毫无疑问,使用new实例的方式,实例化一个Num,它的value将会是1

Num num = new Num();
assertEquals(num.getValue(), 1);

使用Unsafe类的**allocateInstance()**方法,可以实现只为Num类在堆上分配内存,而不调用其构造方法:

public static void allocateInstanceTest() throws InstantiationException {
    Num num = (Num) unsafe.allocateInstance(Num.class);
    System.out.println(num.getV
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值