使用火焰图分析org.apache.commons.beanutils.BeanUtils

Posted m1f2c3

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用火焰图分析org.apache.commons.beanutils.BeanUtils相关的知识,希望对你有一定的参考价值。

一、Java Flight Recorder

参考:https://blog.csdn.net/qq_37552993/article/details/102545780
配置之后让测试程序运行五分钟,得到下面这张图

二、分析耗时原因

2.1 isReadable isWriteable

每次copy时会对每个字段的可读性和可写性进行重复判断,而由于在复制过程中类的结构一般不会改变,所以这俩状态应该被缓存下来。

结论来源:https://blog.csdn.net/u010209217/article/details/84837821

通过反射方式获取可读性和可写性

isPackageAccessible:195, ReflectUtil (sun.reflect.misc)
get:71, MethodRef (java.beans)
getReadMethod:207, PropertyDescriptor (java.beans)
getReadMethod:1256, PropertyUtilsBean (org.apache.commons.beanutils)
isReadable:1435, PropertyUtilsBean (org.apache.commons.beanutils)
copyProperties:281, BeanUtilsBean (org.apache.commons.beanutils)
copyProperties:137, BeanUtils (org.apache.commons.beanutils)
copyProperties:8, CommonsBeanUtilsPropertiesCopier (com.test.BeanutilsTest.copier.Impl)
CommonsBeanUtilsPropertiesCopierTest:25, CopierShowError (com.test.BeanutilsTest)
main:38, CopierShowError (com.test.BeanutilsTest)
isPackageAccessible:195, ReflectUtil (sun.reflect.misc)
getBeanInfo:164, Introspector (java.beans)
getPropertyDescriptors:980, PropertyUtilsBean (org.apache.commons.beanutils)
getPropertyDescriptors:1084, PropertyUtilsBean (org.apache.commons.beanutils)
getPropertyDescriptor:912, PropertyUtilsBean (org.apache.commons.beanutils)
isWriteable:1523, PropertyUtilsBean (org.apache.commons.beanutils)
copyProperties:281, BeanUtilsBean (org.apache.commons.beanutils)
copyProperties:137, BeanUtils (org.apache.commons.beanutils)
copyProperties:8, CommonsBeanUtilsPropertiesCopier (com.test.BeanutilsTest.copier.Impl)
CommonsBeanUtilsPropertiesCopierTest:25, CopierShowError (com.test.BeanutilsTest)
main:38, CopierShowError (com.test.BeanutilsTest)

2.2 StringBuffer.append

输出了大量的日志调试信息

结论来源:https://segmentfault.com/a/1190000019356477

append:262, StringBuffer (java.lang)
convert:1077, BeanUtilsBean (org.apache.commons.beanutils)
copyProperty:437, BeanUtilsBean (org.apache.commons.beanutils)
copyProperties:286, BeanUtilsBean (org.apache.commons.beanutils)
copyProperties:137, BeanUtils (org.apache.commons.beanutils)
copyProperties:8, CommonsBeanUtilsPropertiesCopier (com.test.BeanutilsTest.copier.Impl)
CommonsBeanUtilsPropertiesCopierTest:25, CopierShowError (com.test.BeanutilsTest)
main:38, CopierShowError (com.test.BeanutilsTest)

2.3、getSimpleProperty

与isReadable类似,此函数内调用了getReadMethod以获取读方法,在getReadMethod又进一步调用反射方法,所以性能低。

isPackageAccessible:195, ReflectUtil (sun.reflect.misc)
get:71, MethodRef (java.beans)
getReadMethod:207, PropertyDescriptor (java.beans)
getReadMethod:1256, PropertyUtilsBean (org.apache.commons.beanutils)
getSimpleProperty:1325, PropertyUtilsBean (org.apache.commons.beanutils)
copyProperties:284, BeanUtilsBean (org.apache.commons.beanutils)
copyProperties:137, BeanUtils (org.apache.commons.beanutils)
copyProperties:8, CommonsBeanUtilsPropertiesCopier (com.test.BeanutilsTest.copier.Impl)
CommonsBeanUtilsPropertiesCopierTest:25, CopierShowError (com.test.BeanutilsTest)
main:38, CopierShowError (com.test.BeanutilsTest)

这个函数中获取的读方法实际上已存在于descriptorsCache这个缓存中,但是需要通过反射进一步校验访问权限

校验访问权限。

    Method get() {
        if (this.methodRef == null) {
            return null;
        }
        Method method = this.methodRef.get();
        if (method == null) {
            method = find(this.typeRef.get(), this.signature);
            if (method == null) {
                this.signature = null;
                this.methodRef = null;
                this.typeRef = null;
                return null;
            }
            this.methodRef = new SoftReference<>(method);
        }
        return isPackageAccessible(method.getDeclaringClass()) ? method : null;// 若有权限,返回方法,反之返回null
    }

三、总结

通过火焰图发现StringBuffer.append isReadable isWriteable getSimpleProperty调用时间长,进一步分析发现,耗时问题可以被分为两类,一类是字符串拼接,一类是反射方法isPackageAccessible的调用。

除了上述方法之外,还有很多其他方法也调用了isPackageAccessible

end

以上是关于使用火焰图分析org.apache.commons.beanutils.BeanUtils的主要内容,如果未能解决你的问题,请参考以下文章

异常记录与处理-Cannot find class [org.apache.commons.dbcp.BasicDataSource]

nodejs 应用火焰图简单分析

通过火焰图分析 Node.js 性能(Mac 上)

Firefox 是不是允许使用“聚合”火焰图来分析 JS 应用程序?

使用 org.apache.commons.validator 验证 IBAN

如何在没有 IDE 的情况下使用 Apache Commons Lang 代码? (org.apache.commons.lang3)