基于Unsafe类的对象属性操作工具类

基于Unsafe类的对象属性操作工具类

该工具提供的功能:
1. 提供读取对象的任意类属性和实例化成员的任意属性的值(如直接读取private声明的成员变量值)
2. 提供修改对象任意类属性和实例化成员的任意属性的值(如直接修改final声明的成员变量值)

PS:由于该操作是直接操作内存数据,跳过了Java语法的条框限制,具备一定的危险性,该工具仅做学习和交流使用!

源码GitHub地址

工具代码:

package com.msl.util;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @Discription: 强制读取和操作对象属性工具类
 * @Author Zaki Chen
 * @date 2019/9/30 14:15
 **/
public class ObjectManipulationUtil {

    private static volatile ObjectManipulationUtil util;

    private Unsafe unsafe;

    private ObjectManipulationUtil() {
        try {
            Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeField.setAccessible(true);
            unsafe = (Unsafe) theUnsafeField.get(null);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static ObjectManipulationUtil getInstance() {
        if (util == null) {
            synchronized (ObjectManipulationUtil.class) {
                util = new ObjectManipulationUtil();
            }
        }
        return util;

    }

    /**
     * 获取对象的成员变量属性值
     *
     * @param object       对象实例
     * @param propertyName 对象声明的属性名
     * @param dataType     获取的对象属性的声明类型
     * @return
     * @throws NoSuchFieldException
     */
    public Object getInstanceFieldValue(Object object, String propertyName, Type dataType) throws NoSuchFieldException {
        Field field = object.getClass().getDeclaredField(propertyName);
        long offset = unsafe.objectFieldOffset(field);
        return getValue(object, offset, dataType);
    }

    /**
     * 更新对象实例属性的值
     *
     * @param object       实例对象
     * @param propertyName 实例属性名 非static关键字声明的属性
     * @param val          要修改的值
     * @return
     */
    public void setInstanceFieldValue(Object object, String propertyName, Object val) throws NoSuchFieldException {
        Field propNameField = object.getClass().getDeclaredField(propertyName);
        long offset = unsafe.objectFieldOffset(propNameField);
        Type dataType = getType(val);
        setValue(object, offset, val, dataType);

    }

    /**
     * 修改类属性变量的值
     *
     * @param clazz        类
     * @param propertyName 类属性 static关键字声明的属性
     * @param val          值
     * @throws NoSuchFieldException
     */
    public void setStaticFieldValue(Class clazz, String propertyName, Object val) throws NoSuchFieldException {
        Field propNameField = clazz.getDeclaredField(propertyName);
        long offset = unsafe.staticFieldOffset(propNameField);
        Type dataType = getType(val);
        setValue(clazz, offset, val, dataType);
    }

    /**
     * 获取对象的类变量属性值
     *
     * @param clazz        Class对象
     * @param propertyName 对象类声明的属性名
     * @param dataType     获取的对象类属性的声明类型
     * @return
     * @throws NoSuchFieldException
     */
    public Object getStaticFieldValue(Class clazz, String propertyName, Type dataType) throws NoSuchFieldException {
        Field field = clazz.getDeclaredField(propertyName);
        long offset = unsafe.staticFieldOffset(field);
        return getValue(clazz, offset, dataType);
    }


    /**
     * 数据值类型枚举
     */
    public enum Type {
        /**
         * 引用类型 如String
         */
        Object,
        /**
         * Char类型
         */
        Char,
        /**
         * Byte类型
         */
        Byte,
        /**
         * Integer类型
         */
        Integer,
        /**
         * Double类型
         */
        Double,
        /**
         * Float类型
         */
        Float,
        /**
         * Long类型
         */
        Long,
        /**
         * Boolean类型
         */
        Boolean
    }

    private Type getType(Object val) {
        Type dataType = Type.Object;
        if (val instanceof Character) {
            dataType = Type.Char;
        } else if (val instanceof Byte) {
            dataType = Type.Byte;
        } else if (val instanceof Integer) {
            dataType = Type.Integer;
        } else if (val instanceof Double) {
            dataType = Type.Double;
        } else if (val instanceof Float) {
            dataType = Type.Float;
        } else if (val instanceof Long) {
            dataType = Type.Long;
        } else if (val instanceof Boolean) {
            dataType = Type.Boolean;
        }
        return dataType;
    }

    /**
     * 取对象数据
     *
     * @param object 对象:可以是一个实例对象,也可以是一个类对象
     * @param offset 内存偏移地址
     * @param type   返回数据的类型
     * @return
     */
    private Object getValue(Object object, long offset, Type type) {
        switch (type) {
            case Char:
                return unsafe.getChar(object, offset);
            case Byte:
                return unsafe.getByte(object, offset);
            case Integer:
                return unsafe.getInt(object, offset);
            case Double:
                return unsafe.getDouble(object, offset);
            case Float:
                return unsafe.getFloat(object, offset);
            case Long:
                return unsafe.getLong(object, offset);
            case Boolean:
                return unsafe.getBoolean(object, offset);
            default:
                return unsafe.getObject(object, offset);
        }

    }

    /**
     * 放对象数据
     *
     * @param object 对象:可以是一个实例对象,也可以是一个类对象
     * @param offset 内存偏移地址
     * @param val    修改后的值
     * @param type   被修改属性的声明类型
     */
    private void setValue(Object object, long offset, Object val, Type type) {
        switch (type) {
            case Char:
                unsafe.putCharVolatile(object, offset, (Character) val);
                break;
            case Byte:
                unsafe.putByteVolatile(object, offset, (Byte) val);
                break;
            case Integer:
                unsafe.putIntVolatile(object, offset, (Integer) val);
                break;
            case Double:
                unsafe.putDoubleVolatile(object, offset, (Double) val);
                break;
            case Float:
                unsafe.putFloatVolatile(object, offset, (Float) val);
                break;
            case Long:
                unsafe.putLongVolatile(object, offset, (Long) val);
                break;
            case Boolean:
                unsafe.putBooleanVolatile(object, offset, (Boolean) val);
                break;
            default:
                unsafe.putObjectVolatile(object, offset, val);
        }
    }
}

测试代码:

package com.msl.test01;

import com.msl.util.ObjectManipulationUtil;

/**
 * @Discription:
 * @Author Zaki Chen
 * @date 2019/9/30 14:35
 **/
public class UtilTest01 {
    public static void main(String[] args) {
        Inner inner = new Inner();
        try {
            ObjectManipulationUtil util = ObjectManipulationUtil.getInstance();
            Object value = util.getInstanceFieldValue(inner, "name", ObjectManipulationUtil.Type.Object);
            System.out.println("直接读取到对象的private属性name的值:" + value.toString());
            System.out.println("修改inner对象的name属性值为 ‘叼俊_被修改’");
            util.setInstanceFieldValue(inner, "name", "叼俊_被修改");
            System.out.println("修改后的inner对象的name属性的值为:" + inner.getName());
            System.out.println("----------------------------------------------------");
            Object value2 = util.getStaticFieldValue(Inner.class, "name_static", ObjectManipulationUtil.Type.Object);
            System.out.println("直接读取到类的private属性name_static的值:" + value2.toString());
            util.setStaticFieldValue(Inner.class, "name_static", "叼俊static_被修改");
            System.out.println("修改Inner类的name_static属性的值为:" + Inner.getName_static());
            System.out.println("----------------------------------------------------");
            System.out.println("直接读取Inner对象的name_final属性的值为:"+util.getStaticFieldValue(Inner.class, "name_final", ObjectManipulationUtil.Type.Object));
            util.setStaticFieldValue(Inner.class, "name_final", "叼俊final_被修改");
            System.out.println("修改后Inner对象的name_final属性的值为:"+util.getStaticFieldValue(Inner.class, "name_final", ObjectManipulationUtil.Type.Object));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

class Inner {
    private String name = "叼俊";
    private static String name_static = "叼俊static";
    private static final String name_final = "叼俊final";

    public String getName() {
        return name;
    }

    public static String getName_static() {
        return name_static;
    }

}

测试结果:

"C:\Program Files\Java\jdk1.8.0_51\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar=5777:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_51\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_51\jre\lib\rt.jar;F:\IntellijProjects\concurrent_java\out\production\mima-concurrent" com.msl.test01.UtilTest01
直接读取到对象的private属性name的值:叼俊
修改inner对象的name属性值为 ‘叼俊_被修改’
修改后的inner对象的name属性的值为:叼俊_被修改
----------------------------------------------------
直接读取到类的private属性name_static的值:叼俊static
修改Inner类的name_static属性的值为:叼俊static_被修改
----------------------------------------------------
直接读取Inner对象的name_final属性的值为:叼俊final
修改后Inner对象的name_final属性的值为:叼俊final_被修改

Process finished with exit code 0
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值