反射技巧让你的性能提升N倍

Hi 大家好,我是 DHL。大众号:ByteCode ,专注共享风趣硬核原创内容,Kotlin、Jetpack、功用优化、体系源码、算法及数据结构、动画、大厂面经

在之前的文章和视频中咱们拆分了不同的场景对比反射的功用。

  • 文字版: 侧重于细节上的知识点更多、更加具体,揭秘反射真的很耗时泛型通配符吗,射 10 万次耗时多久
  • 视频版: 经过动画展示讲解,更加的清楚、直观,视频版别 b算法的空间复杂度是指ilibili 地址: b23.tv/Hprua24

在之前的文章中提到了一个提高功用java培训十分重要的点,将 Accessible 设置 true 反射泛型通配符速度会进一步提高,假如单看一个程序,或许这点功用微不足道,可是假java是什么意思如放在一个大的复杂的工程下面,运行在许多的低端机下,一行代码提高的功用,或许比你写 100 行代码提高的功用更加java环境变量配置明显。

而今日这篇文章从源码的角度页面性能优化剖析一下 isAccessible() 办法的作用,为什么将 Accessible 设置为 true 能够提高功用,算法在开端剖析之前,咱们先写一段代码。

  • 声明一个普通类,里面有个 public 办法 gejava语言tName()priva算法te 办法 getAddress()
class Person {
    public fun getName(): String {
        return "I am DHL"
    }
    private fun getAddress(): String {
        return "BJ"
    }
}
  • 经过反射获取 getName()getAddress() 办法,花 3 秒钟考虑一下,下面的代码输出的成果
// public 办法
val method1 = Person::class.declaredFunctions.find { it.name == "getName" }
println("access = ${method1?.isAccessible}")
// private 办法
val method2 = Person::class.declaredFunctions.find { it.name == "getAddress" }
println("access = ${method2?.isAccessible}")

无论是调javaeepublic getNam页面性能优化e()算法的有穷性是指 办法仍是调用 priv泛型编程ate getAddress() 办法,最终输出的成果都为 false动画片少儿小猪佩奇经过这个例子也间接说明晰 isAccessible() 办法并不是用来表明拜访权限的。

当咱们经过反射调用 private 办法时,都需求履行 setAccessible() 办法设置为动画片熊出没 true, 否者会抛出下面的异常。

java.lang.IllegalAccessException: can not access a member of class com.hi.dhl.demo.reflect.Person

假如经过反射调用 public 办法,不设置 Accessibletrue,也能够正常调用,所以有许多小伙伴以为 isAcce算法导论ssible() 办法用来表明拜访权限,其实这种理解是过错的。

咱们一同来看一下源码是怎么解释的,办法 isAccessible() 坐落 AccessibleObject 类中。

public class AccessibleObject implements AnnotatedElement {
    ......
    // NOTE: for security purposes, this field must not be visible
    boolean override;
    public boolean isAccessible() {
        return override;
    }
    public void setAccessible(boolean flag) throws SecurityException {
       ......
    }
    ......
}

Accessi动画片小猪佩奇bleObjectFieldMethodConstructor 的父类,调用 isAccessible() 回来 override 的值,java是什么意思而字段泛型是什么 overridejava语言 首要判算法的特征断是否要进行安全检查。

字段 overrideAccessibleObject 子类傍边运java环境变量配置用,所算法的特征以咱们一同来看一下它的子类 Method

public Object invoke(Object obj, Object... args){
    // 是否要进行安全检查
    if (!override) {
        // 进行快速验证是否是 Public 办法
        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            // 回来调用这个办法的 Class
            Class<?> caller = Reflection.getCallerClass();
            // 做权限拜访的校验,缓存调用这个办法的 Class,防止下次在做检查
            checkAccess(caller, clazz, obj, modifiers);
        }
    }
    ......
    return ma.invoke(obj, args);
}

字段 override 供给给子类去重写,算法它的值决议了是否要进行安全检查,假如要进行安全检查,则会履行 quickCheckMemberAcc动画电影ess() 快速验证是否是 Public 办法,防止调用 getCallerClass()

  • 假如是 Public 办法,防止做安全检查,所以咱们在代泛型通配符码中不调用 setAccessible(true) 办法,也不会抛出异常
  • 假如不是 Public 办法则会调用 getCallerClass() 获取调用这动画片猫和老鼠个办法的 Class,履行 checkAccess() 办法进算法的时间复杂度取决于行安全检查。
// it is necessary to perform somewhat expensive security checks.
// A more complicated security check cache is needed for Method and Field
// The cache can be either null (empty cache)
volatile Object securityCheckCache; // 缓存调用这个办法的 Class
void checkAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers){ 
    ......
    Object cache = securityCheckCache;  // read volatile
    if(cache == 调用这个办法的 Class){
        return;     // ACCESS IS OK
    }
    slowCheckMemberAccess(caller, clazz, obj, modifiers, targetClass);
    ......
}
void slowCheckMemberAccess(Class<?> caller, Class<?> clazz, Object obj, int modifiers,Class<?> targetClass){
    Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
    Object cache = 调用这个办法的 Class
    securityCheckCache = cache;         // 缓存调用这个办法的 Class
}

源码中动画片猫和老鼠注释也说明晰,假如要进行安全检查那么它的代价是十分贵重的,所以用变量 securityCheckCache 缓存调用这个办法的 Class。假如下次运用相同的 Class,就不需求在做安全检查,可java模拟器动画这个缓存有动画电影个缺陷,假如换一个调用这个办法的 Class,需求再次做安全检查,并js性能优化且会覆盖之前的缓存成果。

假如要在运行时修改特点或许调用某个办法时,都要进行动画片少儿小猪佩奇安全检查,而安全检查是十分动画制作软件消耗资源js性能优化的,所以 JDK 供给了一个 setAcce前端性能优化ssible() 办法,能够绕过安全检查,让开发者自己来决议是否要避开安全检查。

因为反射本身是十分慢的,假如能够防止安全检查,能够进一步提高功用,在之前的文章 揭秘反射真的很耗时吗,射 10 万次耗时多久,针对泛型的作用不同场景,别离测验了反射前后以及封闭安全检查的耗时。

正常调用反射反射优化后反射优化后泛型list和普通list有什么区别关掉安全检查
创立目标0.578 ms/op4.710 ms/op1.018 ms/op0.943 ms/op
办法调用0.422 ms/op10.533 ms/op0.844 ms/op0.687 ms/op
特点调用0.241 ms/op12.432 ms/op1.362 ms/op1.202 ms/op
伴生目标0.470 ms/op5.661 ms/op0.840 ms/op0.702 ms/op

从测验成果能够看出来,履行 setAccessible() 办法,设置为 true 关掉安全检查之后,反射速度得到了进一步的提高,更接近于正常调用。

我正在参与技术算法社区创作者签约方案招募活动,点击链接报名投稿。


全文到这里就完毕了,感谢你的阅览,坚持原创不易,欢迎在看、点赞、共享动画片汪汪队给身边的小伙伴,我会动画大放映继续共享原创干货!!!

真诚推荐你重视我,大众号:ByteCode ,继续共享硬核原创内容,Kotl动画电影in、Jetpac动画电影k、功用优化、体系源码、算法及数据结构、动画、大厂面经。



近期必读热门文章

  • 90%人不明白泛型list和普通list有什么区别泛型局限性,泛型擦除,星投影
  • 90%的人都不知道的知识点,Kotlin 和 Java 的协变和逆变
  • CPUjava编译器 怎么记录函数调用进程和回来进程
  • 揭秘反射真的很耗时吗,射 10 万次耗时多久泛型list和普通list有什么区别
  • 你知道 Iterable 有多慢吗?试试算法的时间复杂度取决于它提高功用
  • 揭秘 Kotlin 1.6.20 重磅功用 Context算法是指什么 Receivers
  • Stack Overflow 上最热门的 10 个 Kotlin 问题
  • Andr算法导论oid 12 已来泛型方法,你的 App 溃散了吗?
  • Googl页面性能优化e 宣告废弃 LiveData.observe 办法
  • 影响功用的 Kotlin 代码(一)
  • 揭秘 Kotlin 中的 == 和 ==算法工程师=

最终推荐长时刻更新和保护的项目

  • 个人博客,将一切文章进行分类,欢迎前去检查 hi-dhl.com

  • KtKit 小巧而实用,用 Kotlin 语言编写的工具库,性能优化的方法欢迎前去检查 KtKit

  • 方案树立一个最全、最新的 AndroidX Jetpack 相关组件的实战项目以及相关组件原理剖析文章,正在逐步增加 Jetpa前端性能优化ck 新成员,库房继续更新,欢迎前去检查 AndroidX-Jetpack-Practic算法分析的目的是e

  • L算法的五个特性eetCode / 剑指 offer / 国内外大厂面试题 / 多线程题解,语言 Java 和 kotlin,页面性能优化包含多种解法、解题思路、时刻复杂度、空间复杂度剖析

反射技巧让你的功用提高N倍

  • 剑指 offer 及国内外大厂面试题解:在线阅览
  • LeetCode 系列题解:在线阅览泛型方法的定义和使用

发表评论

提供最优质的资源集合

立即查看 了解详情