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 !"); } }