java为何重复调用方法_通过反射调用Java中的getter:重复调用它的最快方法是什么(在性能和可伸缩性方面)?...
小编典典
您可以使用MethodHandle。其Javadoc写道:
使用Lookup API中的工厂方法,可以将Core Reflection
API对象表示的任何类成员转换为行为等效的方法句柄。例如,可以使用Lookup.unreflect将反射方法转换为方法句柄。生成的方法句柄通常提供对底层类成员的更直接和有效的访问。
虽然这将减少开销,但如果使用常规(非反射)字节代码指令进行调用,则方法句柄仍会阻止JVM可以采用某些优化(此类方法内联)。这种优化是否有益取决于您使用该方法的方式(如果该代码路径始终调用同一方法,则内联可以提供帮助(如果每次都是不同的方法,则可能不会)。
以下微基准可以使您大致了解反射,方法句柄和直接调用的相对性能:
package tools.bench;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.math.BigDecimal;
public abstract class Bench {
final String name;
public Bench(String name) {
this.name = name;
}
abstract int run(int iterations) throws Throwable;
private BigDecimal time() {
try {
int nextI = 1;
int i;
long duration;
do {
i = nextI;
long start = System.nanoTime();
run(i);
duration = System.nanoTime() - start;
nextI = (i << 1) | 1;
} while (duration < 100000000 && nextI > 0);
return new BigDecimal((duration) * 1000 / i).movePointLeft(3);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
return name + "\t" + time() + " ns";
}
static class C {
public Integer foo() {
return 1;
}
}
static final MethodHandle sfmh;
static {
try {
Method m = C.class.getMethod("foo");
sfmh = MethodHandles.lookup().unreflect(m);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws Exception {
final C invocationTarget = new C();
final Method m = C.class.getMethod("foo");
final Method am = C.class.getMethod("foo");
am.setAccessible(true);
final MethodHandle mh = sfmh;
Bench[] marks = {
new Bench("reflective invocation (without setAccessible)") {
@Override int run(int iterations) throws Throwable {
int x = 0;
for (int i = 0; i < iterations; i++) {
x += (Integer) m.invoke(invocationTarget);
}
return x;
}
},
new Bench("reflective invocation (with setAccessible)") {
@Override int run(int iterations) throws Throwable {
int x = 0;
for (int i = 0; i < iterations; i++) {
x += (Integer) am.invoke(invocationTarget);
}
return x;
}
},
new Bench("methodhandle invocation") {
@Override int run(int iterations) throws Throwable {
int x = 0;
for (int i = 0; i < iterations; i++) {
x += (Integer) mh.invokeExact(invocationTarget);
}
return x;
}
},
new Bench("static final methodhandle invocation") {
@Override int run(int iterations) throws Throwable {
int x = 0;
for (int i = 0; i < iterations; i++) {
x += (Integer) sfmh.invokeExact(invocationTarget);
}
return x;
}
},
new Bench("direct invocation") {
@Override int run(int iterations) throws Throwable {
int x = 0;
for (int i = 0; i < iterations; i++) {
x += invocationTarget.foo();
}
return x;
}
},
};
for (Bench bm : marks) {
System.out.println(bm);
}
}
}
在我有些过时的笔记本上
java version "1.7.0_02"
Java(TM) SE Runtime Environment (build 1.7.0_02-b13)
Java HotSpot(TM) Client VM (build 22.0-b10, mixed mode, sharing)
打印:
reflective invocation (without setAccessible) 568.506 ns
reflective invocation (with setAccessible) 42.377 ns
methodhandle invocation 27.461 ns
static final methodhandle invocation 9.402 ns
direct invocation 9.363 ns
更新:正如Irreputable所指出的那样,服务器VM具有一些不同的性能特征,因此
,仅当您可以将MethodHandle放在静态final字段中时 ,在 服务器VM中使用MethodHandle才有帮助
,在这种情况下,VM可以内联调用:
reflective invocation (without setAccessible) 9.736 ns
reflective invocation (with setAccessible) 7.113 ns
methodhandle invocation 26.319 ns
static final methodhandle invocation 0.045 ns
direct invocation 0.044 ns
我建议您衡量您的特定用例。
2020-09-18
java为何重复调用方法_通过反射调用Java中的getter:重复调用它的最快方法是什么(在性能和可伸缩性方面)?...相关推荐
- java 格式化日期到毫秒_关于日期:Java – SimpleDateFormat格式化程序,以毫秒为单位返回纪元时间...
本问题已经有最佳答案,请猛点这里访问. 我是Java和编码的新手 - 我有一些代码以下列格式yyyy.MM.dd HH:mm:ss:ms返回时间戳,如下所示: SimpleDateFormat for ...
- python如何创建一个列表_在python中创建列表的最佳和/或最快方法
在python中,据我所知,至少有3到4种方法来创建和初始化给定大小的列表: 简单循环append: my_list =[]fori inrange(50):my_list.append(0) 简单循 ...
- 在python中创建列表的最佳和/或最快方法
在python中,据我所知,至少有3到4种方法来创建和初始化给定大小的列表: 简单循环append: my_list = [] for i in range(50):my_list.append(0) ...
- java 找出调用的方法_如何找到用Java调用给定方法的所有方法?
小编典典 为了分析字节码,我建议使用ASM.给定要分析的类列表,可以使访问者找到您感兴趣的方法调用.下面是一个分析jar文件中类的实现. 请注意,ASM使用带有'/'而不是'.的internalNam ...
- java子类调用抽象父类方法_【坑】Spring中抽象父类属性注入,子类调用父类方法使用父类注入属性...
运行环境 idea 2017.1.1 spring 3.2.9.RELEASE 需求背景 需要实现一个功能,该功能有2个场景A.B,大同小异 抽象一个抽象基类Base,实现了基本相同的方法BaseMe ...
- java代码安全检测机制_全面解析:java中的反射机制,内含代码验证解析
什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功 ...
- java list sublist方法_(转)Java 中 List.subList() 方法的使用陷阱
原文:http://blog.csdn.net/cleverGump/article/details/51105235 前言 本文原先发表在我的 iteye博客: http://clevergump. ...
- main方法_你知道为什么Java的main方法必须是public static void?
来源:http://suo.im/6v9d64 Main 方法是我们学习 Java 编程语言时知道的第一个方法,你是否曾经想过为什么 main 方法是 public.static.void 的.当然, ...
- java clone方法_干货满满:Java中创建对象的五种方式详解
通常来说,对象具有状态和行为,变量用来表明对象的状态,方法表明对象所具有的行为. 作为Java开发者,我们通常都是使用依赖管理系统,比如Spring去创建Java对象,但使用管理系统创建对象并不是唯一 ...
最新文章
- startActivityForResult和setResult详解
- Throwable是java.lang包中一个专门用来处理异常的类
- QLable显示图片 和 QLabel自适应 QLabel 文字居中
- python中shift_python对列进行平移变换的方法(shift)
- RedisDesktopManager客户端可视化工具下载安装与使用
- NOKIA Update for Windows Phone
- word2003如何设置护眼模式_ERP系统上线,如何设置采购收货的模式,提升企业的采购效率...
- hdu 2196 computer
- python字符串转浮点数_Python | 打印不同的值(整数,浮点数,字符串,布尔值)...
- 信息学奥赛一本通 1182:合影效果 | OpenJudge NOI 1.10 07:合影效果
- 《Reids 设计与实现》第三章 跳跃表
- 分表扩展全局序列实际操作_高可用_单表存储千万级_海量存储_分表扩展---MyCat分布式数据库集群架构工作笔记0026
- 苹果发布会不够酷?库克又送来了 iOS 12.2!
- 嵌入式学习流程(参考一)
- java修饰符super_Java 继承 方法重写 super关键字 访问权限修饰符
- .tar.bz2 解压出错问题解决方案
- VGA显示原理、时序标准及相关参数
- SAEJ1757-1-2015(一)
- 网站内容采集工具介绍
- 微信小程序新版canvas绘制图片方法
热门文章
- dj打碟怎么学_学DJ打碟 - Rane声卡连接
- 【51单片机快速入门指南】4.4:I2C 读取HMC5883L / QMC5883L 磁力计
- 【51单片机快速入门指南】3:中断系统
- 非常全的VsCode快捷键
- 公布生成cscope.out, cscope.files, tags的脚本文件
- uni-app自定义tabBar;uni-app小程序自定义tabBar;uni-app小程序修改中间tabBar导航栏大小;uni-app中间导航栏凸起;uni-app修改底部导航栏
- 简单的封装axios 不包含状态码和提示
- 前端学习(3100):vue+element今日头条管理-react简介
- [html] html标签的属性值是否可以省略引号?为什么?
- 工作380-js判断是否为空