Java Unsafe 测试代码

 

Java Unsafe 测试代码

import com.User;
import org.junit.Before;
import org.junit.Test;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;

class User {

    public static String USER_CLASS_NAME = "User.class";
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class LockTests {

    Unsafe unSafe;
    User u = new User(17, "zhangsan");

    @Before
    public void before() throws Exception {
        Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafeField.setAccessible(true);
        unSafe = (Unsafe) theUnsafeField.get(Unsafe.class);
    }

    @Test
    public void objectFieldOffset() throws Exception {
        // unSafe偏底层的一个Java工具类
        java.util.List users = new ArrayList();
        for (int i = 0; i < 10; i++) {
            Field ageField = User.class.getDeclaredField("age");
            User u = new User(18, "daxin");
            users.add(u);
            //使用内存获取User age字段在内存中的 offset
            // 是相对地址,不是一个绝对地址
            long ageOffset = unSafe.objectFieldOffset(ageField);
            // 每次都相同
            System.out.println("ageOffset = " + ageOffset);
        }
    }

    @Test
    public void compareAndSwapInt() throws Exception {

        // unSafe偏底层的一个Java工具类
        Field ageField = User.class.getDeclaredField("age");

        User u = new User(18, "daxin");

        //使用内存获取User age字段在内存中的 offset
        long ageOffset = unSafe.objectFieldOffset(ageField);

        // 修改之前的值
        System.out.println(u.getAge());
        // 进行CAS更新, 由于设置18 因此CAS 会成功
        unSafe.compareAndSwapInt(u, ageOffset, 18, 20);
        System.out.println(u.getAge());

        // 由于age设置20  进行CAS失败
        unSafe.compareAndSwapInt(u, ageOffset, 18, 22);
        System.out.println(u.getAge());

    }

    @Test
    public void ensureClassInitialized() {
        System.out.println("==== start ====");
        unSafe.ensureClassInitialized(ClassIsLoad.class);
        // 再次 确认不会报错
        unSafe.ensureClassInitialized(ClassIsLoad.class);
    }

    /**
     * AQS 底层的Node链表就是基于这个工具实现的 。
     *
     * @throws Exception
     */
    @Test
    public void getValueByFieldOffset() throws Exception {
        for (int i = 0; i < 10; i++) {
            User u = new User(18, UUID.randomUUID().toString().substring(i, 20));
            int age = unSafe.getInt(u, 12L);
            System.out.println("age = " + age);

            // 获取名字 field offset
            Field nameField = User.class.getDeclaredField("name");
            long nameOffset = unSafe.objectFieldOffset(nameField);
            System.out.println("nameOffset = " + nameOffset);
            String name = unSafe.getObject(u, nameOffset) + "";
            System.out.println("name = " + name);
        }
    }

    @Test
    public void pageSize() {
        System.out.println("unSafe.pageSize() = " + unSafe.pageSize());
    }

    /**
     * AtomicInteger 底层是基于getAndAddInt实现
     */
    @Test
    public void getAndAddInt() throws InterruptedException {

        User u = new User(17, "zhangsan");
        CountDownLatch downLatch = new CountDownLatch(10);
        System.out.println("u.getAge() = " + u.getAge());
        for (int i = 0; i < 10; i++) {

            new Thread(new Runnable() {
                @Override
                public void run() {
                    downLatch.countDown();
                    int val = unSafe.getAndAddInt(u, 12L, 1);
                    System.out.println(Thread.currentThread().getName() + "  val = " + val);
                }
            }).start();

        }
        Thread.sleep(5000);
        System.out.println("u.getAge() = " + u.getAge());
    }

    @Test
    public void getAndSetInt() throws InterruptedException {
        User u = new User(17, "zhangsan");
        CountDownLatch downLatch = new CountDownLatch(10);
        System.out.println("u.getAge() = " + u.getAge());
        for (int i = 0; i < 10; i++) {

            new Thread(new Runnable() {
                @Override
                public void run() {
                    downLatch.countDown();
                    int val = unSafe.getAndSetInt(u, 12L, 10);
                    System.out.println(Thread.currentThread().getName() + "  val = " + val);
                }
            }).start();

        }
        Thread.sleep(5000);
        System.out.println("u.getAge() = " + u.getAge());
    }


    @Test
    public void getIntVolatile() {

        for (int i = 0; i < 10; i++) {
            u.setAge(i);
            /**
             * @param obj    the object containing the field to modify.
             * @param offset the offset of the integer field within <code>obj</code>.
             * @return
             */
            int age = unSafe.getIntVolatile(u, 12L);
            System.out.println("age = " + age);
        }
    }

    // 系统负载采样的接口
    @Test
    public void getLoadAverage() {
        double[] nums = new double[8];
        int val = unSafe.getLoadAverage(nums, 8);
        System.out.println(val);
    }


    /**
     * //内存屏障,禁止load操作重排序。屏障前的load操作不能被重排序到屏障后,屏障后的load操作不能被重排序到屏障前
     * public native void loadFence();
     * <p>
     * <p>
     * 参见:https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
     */

    @Test
    public void loadFence() {
        //java.util.concurrent.locks.StampedLock.validate
        unSafe.loadFence();
    }

    /**
     * //内存屏障,禁止store操作重排序。屏障前的store操作不能被重排序到屏障后,屏障后的store操作不能被重排序到屏障前
     * public native void storeFence();
     * 参见:https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
     */
    @Test
    public void storeFence() {
    }

    /**
     * //内存屏障,禁止load、store操作重排序
     * public native void fullFence();
     * 参见:https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
     */
    @Test
    public void fullFence() {
    }


    @Test
    public void shouldBeInitialized() {
        boolean shouldBeInitialized = unSafe.shouldBeInitialized(String.class);
        System.out.println(shouldBeInitialized);
        shouldBeInitialized = unSafe.shouldBeInitialized(User.class);
        System.out.println(shouldBeInitialized);
    }

    /**
     * synchronized 的一种实现获取锁
     *
     * @throws InterruptedException
     */
    @Test
    public void monitorEnter() throws InterruptedException {

        unSafe.monitorEnter(u);
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (u) {
                    System.out.println("==u lock got ==");
                }
            }
        }).start();

        Thread.sleep(2000);
        unSafe.monitorExit(u);
    }

    @Test
    public void compareAndSwap() {
//        unSafe.compareAndSwapInt(对象, 对象中的字段偏移, 期望值, 设置值)
//        unSafe.compareAndSwapLong(对象, 对象中的字段偏移, 期望值, 设置值)
//        unSafe.compareAndSwapObject(对象, 对象中的字段偏移, 期望值, 设置值)
    }

    @Test
    public void t() {
        // 方法签名
        // public void copyMemory(Object srcBase, long srcOffset,Object destBase, long destOffset, long bytes)
        // unSafe.copyMemory();
    }


}


class ClassIsLoad {

    static {
        System.out.println("ClassIsLoad class Is Load !");
    }
}

  

上一篇:【Java杂记】魔术类:Unsafe 的四种核心功能及应用场景


下一篇:并发编程之sun.misc.Unsafe类