• unsafe中方法的使用


    创建目标对象

        static class Simple{
            private long l = 0;
            
            public Simple() {
                this.l = 1;
                System.out.println("==================");
            }
            
            public long get() {
                return this.l;
            }
        }

    创建对象实例的三种方法

    方法一:

    Simple simple1 = new Simple();
    System.out.println(simple1.get());

    方法二:

            Simple simple2 = Simple.class.newInstance();
            System.out.println(simple2.get());

    方法三:

            //绕过了类的初始化阶段
            Class<?> simple3 = Class.forName("com.dwz.atomicApi.UnsafeFooTest$Simple");

    创建unsafe:

        private static Unsafe getUnsafe() {
            try {
                Field f = Unsafe.class.getDeclaredField("theUnsafe");
                f.setAccessible(true);
                return (Unsafe) f.get(null);
            } catch (Exception e) {
                throw new RuntimeException(e);
            } 
        }

    使用unsafe来绕过构造方法创建对象:

            Unsafe unsafe = getUnsafe();
            //开辟内存
            Simple simple4 = (Simple)unsafe.allocateInstance(Simple.class);
            System.out.println(simple4.get());
            System.out.println(simple4.getClass());
            System.out.println(simple4.getClass().getClassLoader());

    结果如下:

    0
    class com.dwz.atomicApi.UnsafeFooTest$Simple
    sun.misc.Launcher$AppClassLoader@73d16e93

    使用unsafe的方式给类的字段赋值

    目标对象:

        static class Guard{
            private int ACCESS_ALLOWED = 1;
            
            private boolean allow() {
                return 42 == ACCESS_ALLOWED;
            }
            
            public void work() {
                if(allow()) {
                    System.out.println("I am working by allowed.");
                }
            }
        }

    测试方法:

            Unsafe unsafe = getUnsafe();
            Guard guard = new Guard();
            
            Field f = guard.getClass().getDeclaredField("ACCESS_ALLOWED");
            unsafe.putInt(guard, unsafe.objectFieldOffset(f), 42);
            guard.work();

    测试结果:

    I am working by allowed.

    使用unsafe读取.class文件

    目标对象A.class

    package com.dwz.atomicApi;
    
    public class A {
        private int i = 0;
        
        public A() {
            this.i = 1;
        }
        
        public int get() {
            return this.i;
        }
    }
        /**
         *     将要加载的文件读到字节数组中去
         * @throws IOException 
         */
        private static byte[] loadClassContent() throws IOException {
            File f = new File("E:\mySoftware\eclipse-workspace\concurrency\target\classes\com\dwz\atomicApi\A.class");
            FileInputStream fis = new FileInputStream(f);
            byte[] content = new byte[(int)f.length()];
            fis.read(content);
            fis.close();
            return content;
        }

    测试方法:

            Unsafe unsafe = getUnsafe();
            //该方式也会进行初始化
            byte[] bytes = loadClassContent();
            Class aClass = unsafe.defineClass(null, bytes, 0, bytes.length, null, null);
            int v = (int)aClass.getMethod("get", null).invoke(aClass.newInstance(), null);
            System.out.println(v);

    使用unsafe自定义一个sizeOf方法:

        public static long sizeOf(Object obj) {
            Unsafe unsafe = getUnsafe();
            Set<Field> fields = new HashSet<Field>();
            Class c = obj.getClass();
            while(c != Object.class) {
                Field[] declareedFields = c.getDeclaredFields();
                for(Field f : declareedFields) {
                    if((f.getModifiers() & Modifier.STATIC) == 0) {
                        fields.add(f);
                    }
                }
                
                c = c.getSuperclass();
            }
            
            long maxOffSet = 0;
            for(Field f : fields) {
                long offset = unsafe.objectFieldOffset(f);
                if(offset > maxOffSet) {
                    maxOffSet = offset;
                }
            }
            
            return ((maxOffSet/8)+1)*8;
        }
  • 相关阅读:
    VS2010 Extension实践(3)——实现自定义配置
    VS2010 Extension实践(2)
    WinRT开发系列之基础概念:WinRT不是……
    [VS2010 Extension]PowerExtension.GoToDefinition
    如何通过反射调用带有ref或者out的参数的方法[迁移]
    Win7硬盘安装和移动硬盘访问出错的修复办法[迁移]
    zt. Windows Mobile开发文章收藏
    WinRT开发系列之编程语言:功能和效率
    VS2010 Extension实践
    maven创建父子工程
  • 原文地址:https://www.cnblogs.com/zheaven/p/13181996.html
Copyright © 2020-2023  润新知