码迷,mamicode.com
首页 > 其他好文 > 详细

反射、Unsafe、直接调用性能大比拼

时间:2020-01-27 00:18:38      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:nsa   blog   lin   code   字符   动态表   oschina   erro   call   

  在java动态表达式、原生调用、反射性能对比这一篇的基础上,本文我们将比较原生调用和直接通过Unsafe指针操作java对象的性能。

package com.hundsun.jrescloud;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @author zjhua
 * @description
 * @date 2020/1/26 20:20
 */
public class TestUnSafe {
    static final Unsafe unsafe;
    static final long stateOffset;
    static final long volStateOffset;
    private volatile long volState = 0;
    private long state = 0;

    static {
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
            stateOffset = unsafe.objectFieldOffset(TestUnSafe.class.getDeclaredField("state"));
            volStateOffset = unsafe.objectFieldOffset(TestUnSafe.class.getDeclaredField("volState"));
        } catch (Exception ex) {
            System.out.println(ex.getLocalizedMessage());
            throw new Error(ex);
        }
    }

    public static void main(String[] args) {
        TestUnSafe test = new TestUnSafe();
        long beg = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            unsafe.putLong(test, stateOffset,i);
        }
        System.out.println("unsafe put non volatile: " + (System.currentTimeMillis() - beg));
        beg = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            test.state = i;
        }
        System.out.println("pojo put non volatile: " + (System.currentTimeMillis() - beg));

        beg = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            unsafe.putLong(test, stateOffset,i);
        }
        System.out.println("unsafe put volatile: " + (System.currentTimeMillis() - beg));
        beg = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            test.volState = i;
        }
        System.out.println("pojo put volatile: " + (System.currentTimeMillis() - beg));
    }
}

  输出如下:

unsafe put non volatile: 179  // 普通属性,直接操作更快。如果使用setter的话,则有时候unsafe快,有时候pojo快。
pojo put non volatile: 68  
unsafe put volatile: 114   // volatile属性,unsafe要快近6倍。
pojo put volatile: 795

  对于字符串操作,上述结论亦成立。

  除了get/put外,Unsafe类还包含很多CAS功能(JUC很多原子和CAS就是基于Unsafe实现)、park、unpark功能。

  注:Reflection.getCallerClass(n)已经被废弃,不应该再使用,它主要用来跟踪哪些类调用了本方法,不过Reflection.getCallerClass()仍然可用,在跟踪工具类的时候时还是比较有用的。

  关于Unsafe更全面的使用介绍,可以参见https://my.oschina.net/editorial-story/blog/3019773。

反射、Unsafe、直接调用性能大比拼

标签:nsa   blog   lin   code   字符   动态表   oschina   erro   call   

原文地址:https://www.cnblogs.com/zhjh256/p/10741400.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!