zoukankan      html  css  js  c++  java
  • Unsafe 的简单使用

    Unsafe 简介

    Unsafe 是sun.misc包中的一个类,可以通过内存偏移量操作类变量/成员变量

    Unsafe 用途

    AQS(AbstractQueuedSynchronizer) 常用作实现轻量级锁,它里面有一个双向链表,用于封装未抢到锁的线程 ,其中有用到UnsafecompareAndSwapObject修改链表

    Unsafe 简单使用示例

    package com.xh.kssfwjg.idgenerator;
    
    import sun.misc.Unsafe;
    
    import java.lang.reflect.Field;
    
    /**
     * TODO
     *
     * @auther xh
     * @date 12/26/18 6:11 PM
     */
    public class UnSaveTest {
        private static final Unsafe unsafe = getUnsafe();
        private static final long objectNameOffset;
        private static final long staticNameOffset;
    
        private static String staticName = "qq";
        private String objectName = "123";
    
        static {
            try {
                objectNameOffset = unsafe.objectFieldOffset
                        (UnSaveTest.class.getDeclaredField("objectName"));
                staticNameOffset = unsafe.staticFieldOffset(UnSaveTest.class.getDeclaredField("staticName"));
            } catch (NoSuchFieldException e) {
                throw new Error(e);
            }
        }
    
        public static void main(String[] args) {
            UnSaveTest unSaveTest = new UnSaveTest();
            // unsafe.compareAndSwapObject(unSaveTest, testOffset, "123", "456");//CAS
            unsafe.putObject(unSaveTest, objectNameOffset, "haha");//直接修改
            unsafe.putObject(UnSaveTest.class, staticNameOffset, "hehe");//直接修改
            System.out.println(unSaveTest.objectName);
            System.out.println(UnSaveTest.staticName);
        }
    
    
        private static Unsafe getUnsafe() {
            Field singleoneInstanceField = null;
            try {
                singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
                singleoneInstanceField.setAccessible(true);
                return (Unsafe) singleoneInstanceField.get(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
    

    output:

    haha
    hehe
    

    ps:

    如果变量使用final修饰,如:

    private static final String staticName = "qq";
    private final String objectName = "123";
    

    是不能修改的.

    另外附上反射的示例

            try {
                Class clazz = Class.forName("com.xh.kssfwjg.idgenerator.UnSaveTest");
                Object o = clazz.newInstance();
                Field object_field_name = clazz.getDeclaredField("objectName");
                object_field_name.setAccessible(true);
                object_field_name.set(o, "ooo");
    
                Field static_field_name = clazz.getDeclaredField("staticName");
                static_field_name.setAccessible(true);
                static_field_name.set(clazz, "ppp");
    
                System.out.println(UnSaveTest.staticName);
                System.out.println(((UnSaveTest) o).objectName);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
    

    结果一样

  • 相关阅读:
    php 发送手机验证码
    PHP 发送邮件
    php 图形验证码
    css 把图片变成灰色
    本地配置虚拟主机
    VMware 14 激活密钥
    linux每日命令(12): nl 命令
    linux每日命令(11): cat命令
    linux每日命令(10): touch命令
    linux每日命令(9): cp命令
  • 原文地址:https://www.cnblogs.com/lanqie/p/10181363.html
Copyright © 2011-2022 走看看