实现方式
有两种不同的实现方式,一种是本地实现,一种是动态实现。
JVM开始运行之后,方法的代码和入口地址都能获取到,想要通过反射调用方法,无非就是找到方法地址,然后将参数传递进去执行。
本地实现就是使用native方法直接调用方法。但是这种方法涉及到java代码调用c++代码,单次调用性能较差。
动态实现是指通过字节码工具生成一个中间类,这个中间类直接调用目标方法,因此单次调用性能跟直接调用基本没有区别。但是生成动态类,以及动态类字节码的解释执行在首次执行是耗时很长。
所以jvm对于调用次数很少的方法仍然采用本地实现,调用次数超过阈值(默认是15次)时才会为其生成动态来进行直接调用。
反射慢的原因
反射方法的调用相较于正常直接调用速度较慢,这与反射调用的方法息息相关,Method.invoke方法接收的参数是Object类型的变长参数,在执行时会首先生成一个Object数组,然后将参数依次装入数组中传入。其次Object数组无法存放基本类型,因此原方法参数若是基本类型就必然牵涉到基本型的装箱拆箱。最后原方法直接调用时有可能会被即时编译器进行方法内联进一步提高运行速度,但是反射会影响方法内联。