黄岛天气,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版

频道:国际新闻 日期: 浏览:261

预备常识

  1. 了解 Java 反射根本用法

看完本文能够到达什么程度

  1. 了解 Java 反射原理及 Java 反射功率低的原因

文章概览

咱们在 Java 开发中,黄岛气候,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版难免会接触到反射,而在一些结构中,反射的运用更是常见。我信任,每次说到反射,咱们的榜首反响一黄岛气候,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版定是反射功率低,尽量少运用。

可是反射的功率究竟低多少?反射功率低的原因在哪里?

这篇文章就来探究一下这些问题。

由于本机上装置的是 openjdk 12,所以这儿就运用 openjdk 12 源码进行剖析。

咱们先看定论,然后剖析一下 Java 反射的原理,过程中咱们能够依据定论,对源码做一些考虑,然后再依据原理中的一些完成,看看 Java 反射功率低的原因。

零、先放定论

Java 反射功率低首要原因是:

  1. Method#invoke 办法会对参数做封装和解封操作
  2. 需求查看办法可见性
  3. 需求校验参数
  4. 反射办法难以内联
  5. JIT 无法优化

一、Java 反射原理--获取要反射的办法

1.1 反射的运用

咱们先来看看 Java 反射运用的一段代码:

public class RefTest {
public static void main(String[] args) {
try {
Class clazz = Class.forName("com.zy.java.RefTest");
Object refTest = clazz.newInstance();
Method method = clazz.getDeclaredMethod("refMethod");
method.invoke(refTest);
} catch (Exception e) {
e.printStackTrace();
}
}
public void refMethod() {
}
}

咱们在调用反射时,首先会创立 Class 目标,然后获取其 Method 目标,调用 invoke 办法。

获取反射办法时,有两个办法,getMethod 和 getDeclaredMethod,咱们就从这两个办法开端,一步步看下反射的原理。

接下来就进入代码剖析,咱们做好预备。

1.2 getMethod / getDeclaredMethod

这儿咱们先全体看一下 getMethod 和 getDeclaredMethod 的完成。

class Class {

@CallerSensitive

public Method getMethod(String name, Class

throws NoSuchMethodException, SecurityException {

Objects.requireNonNull(name);

SecurityManager sm = System.getSecurityManager();

if (sm != null) {

// 1. 查看办法权限

checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), true);

}

// 2. 获取办法

Method method = getMethod0(name, parameterTypes);

if (method == null) {

throw new NoSuchMethodExcep洋洋很高兴tion(methodToString(name, parameterTypes));

}

// 3. 回来办法的复制

return getReflectionFactory().copyMethod(method);

}

@CallerSensitive

public Method getDeclaredMethod(String name, Class

throws NoSuchMethodException, SecurityException {

Objects.requireNonNull(name);

SecurityManager sm = System.getSecurityManager();

if (sm != null) {

// 1. 查看办法是权限

checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);

}

// 2. 获取办法

Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);

if (method == nu吉雪萍第三次怀孕ll) {

throw new NoSuchMethodException(methodToString(name, parameterTypes));

}

// 3. 回来办法的复制

return getReflectionFactory().copyMethod(method);

}

}

从上面的代码,咱们能够看到,获取办法的流程分三步走:

  1. 查看办法权限
  2. 获取办法 Method 目标
  3. 回来办法的复制

这儿首要有两个差异:

  1. getMethod 中 checkMemberAccess 传入的是 Member.PUBLIC,而 getDeclaredMethod 传入的是 Member伊情面.DECLARED 这两个值有什么差异呢?咱们看下代码中的注释:
interface Member {
/**
* Identifies the set of all public members of a class or interface,
* including inherited members.
*/
public static final int PUBLIC = 0;
/**
* Identifies the set of declared members of a class or interface.
* Inherited members are not included.
*/
public static final int DECLARED = 1;
}

注释里清楚的解说了 PUBLIC 和 DECLARED 的不同,PUBLIC 会包含一切的 public 办法,包含父类的办法,而 DECLARED 会包含一切自己界说的办法,public,protected,private 都在此,可是不包含父类的办法。

这也正是 getMethod 和 getDeclaredMethod 的差异。

2. getMethod 中获取办法调用的是 getMethod0,而 getDeclaredMethod 获取办法调用的是 privateGetDeclaredMethods 关于这个差异,这儿简略提及一下,后边详细剖析代码。

privateGetDeclaredMethods 是获取类本身界说的办法,参数是 boolean publicOnly,表明是否只获取公共办法。

private Method[] privateGetDeclaredMethods(boolean publicOnly) {

//...

}

而 getMethod0 会递归查找父类的办法,其间会调用到 privateGetDeclaredMethods 办法。

已然咱们上面看了 getMethod 和 getDeclaredMethod 的差异,咱们黄岛气候,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版自然挑选 getMethod 办法进行剖析,这样能够走到整个流程。

1.3 getMethod 办法

getMethod 办法流程如下图:

class Class {
public Method getMethod(String name, Class
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// 1. 查看办法权限
checkMemberAcce白姐网ss(sm, Member.PUBLIC, Reflection.getCallerClass(), true);
}
// 2. 获取办法 Method 目标
Method method = getMethod0(name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
// 3. 回来办法复制
return getReflectionFactory().copyMethod(method);
}
}

咱们上面说到获取办法分三步走:

  1. 查看办法权限
  2. 获取办法 Method 目标
  3. 回来办法的复制

咱们先看看查看办法权限做了些什么事情。

1.3.1 checkMemberAccess

class Class {

private void checkMemberAccess(SecurityManager sm, int which,

Class

/* Default policy allows access to all {@link Member#PUBLIC} members,

* as well as access to classes that have the same class loader as the caller.

* In all other cases, it requires RuntimePermission("accessDeclaredMembers")

* permission.

*/

final ClassLoader ccl = ClassLoader.getClassLoader(caller);

if (which != Member.PUBLIC) {

final ClassLoader cl = getClassLoader0();

if (ccl != cl) {

sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);

}

}

this.checkPackageAccess(sm, ccl, checkProxyInterfaces);

}

}

在这儿能够看到,关于非 Member.PUBLIC 的拜访,会添加一项检测,SecurityManager.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); 这项检测需求运转时请求 RuntimePermission("accessDeclaredMembers")。

这儿就不持续往下看了,办法全体是在查看是否能够拜访目标成员。

接着看下是怎样获取办法的 Method 目标。

1.3.2 getMethod0

class Class {
private Method getMethod0(String name, Class
PublicMethods.MethodList res = getMethodsRecursive(
name,
parameterTypes == null ? EMPTY_CLASS_ARRAY : parameterTypes,
/* includeStatic */ true);
return res == null ? null : res.getMostSpecific();
}
}

这儿是经过 getMethodsRecursive 获取到 MethodList 目标,然后经过 MethodList#getMostSpecific 办法挑选出对应的办法。 MethodList#getMOstSpecific 会挑选回来值类型最为详细的办法,至于为什么会有回来值的差异,后边会讲到。

(这儿的详细,指的是有两个办法,回来值分别是 Child 和 Parent,Child 承继自 Parent,这儿会挑选出回来值为 Child 的办法)。

接着看 getMethodsRecursive 办法,是怎样获取办法的。

1.3.3 getMethodsRecursive

class Class {

private PublicMethods.MethodList getMethodsRecursive(String name,

Class

boolean includeStatic) {

// 1. 获取自己的 public 办法

Method[] methods = privateGetDeclaredMethods(/* publicOnly */ true);

// 2. 挑选契合条件的办法,结构 MethodList 目标

PublicMethods.MethodList res = PublicMethods.MethodList

.filter(methods, name, parameterTypes, includeStatic);

// 找到办法,直接回来

if (res != null) {

return res;

}

// 3. 没有找到办法,就获取其父类,递归调用 getMethodsRecursive 办法

Class

if (sc != null) {

res = sc.getMethodsRecursive(name, parameterTypes, includeStatic);

}

// 4. 获取接口中对应的办法

for (Class

res = PublicMethods.MethodList.merge(

res, intf.getMethodsRecursive(name, parameterTypes,

/* includeStatic */ false));

}

return res;

}

}

这儿获取办法有四个过程:

  1. 经过 privateGetDeclaredMethods 获取自己一切的 public 办法
  2. 经过 MethodList#filter 查找 办法名,参数相同的办法,假如找到,直接回来
  3. 假如自己没有完成对应的办法,就去父类中查找对应的办法
  4. 查找接口中对应的办法

经过上面四个过程,终究获取到的是一个 MethodList 目标,是一个链表结点,黄岛气候,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版其 next 指向下一个结点。也便是说,这儿获取到的 M费玉清姐姐ethod 会有多个。

这儿略微解说一下,在咱们平常编写 Java 代码时,同一个类是不能有办法名和办法参数都相同的办法的,而实践上,在 JVM 中,一个办法签名是和 回来值,办法名,办法参数 三者相关的。 也便是说,在 JVM 中,能够存在 办法名和办法参数都相同,可是回来值不同的办法。

所以这儿回来的是一个办法链表。

所以上面终究回来办法时会经过 MethodList#getMostSpecific 进行回来值的挑选,挑选出回来红通黄红回国投案值类型最详细的办法。

这儿咱们先暂停回忆一下全体的调用链路:

getMethod -> getMethod0 -> getMethodsRecursive -> privateGetDeclaredMethods

经过函数调用,终究会调用到 privateGetDeclaredMethods 办法,也便是真实获取办法的当地。

1.3.4 privateGetDeclaredMethods

class Class {

private Method[] privateGetDeclaredMethods(boolean publicOnly) {

Method[] res;

// 1. 经过缓存获取 Method[]

ReflectionData rd = reflectionData();

if (rd != null) {

res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;

if (res != null) return res;

}

// 2. 没有缓存,经过 JVM 获取

res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));

if (rd != null) {

if (publicOnly) {

rd.declaredPublicMethods = res;

} else {

rd.declaredMethods = res;

}

}

return res;

}

}

在 privateGetDeclaredMethodsislider 获取办法时,有两个过程:

  1. relectionData 经过缓存获取
  2. 假如缓存没有射中的话,经过 getDeclaredMethods九趣英语0 获取办法

先看看 relectionData 办法:

class Class {
private ReflectionData reflectionData() {
SoftReference> reflectionData = this.reflectionData;
int classava视频Redefin草我edCount = this.classRedefinedCount;
ReflectionData rd;
if (reflectionData != null &&
(rd = reflectionData.get()) != null &&
rd.redefinedCount == classRedefinedCount) {
return rd;
}
// else no SoftReference or cleared SoftReference or stale ReflectionData
// -> create and replace new instance
return newReflectionData(reflectionData, classRedefinedCount);
}
}

在 Class 中会保护一个 ReflectionData 的软引证,作为反射数据的缓存。

ReflectionData 结构如下:

 private static class ReflectionData {
volatile Field[] declaredFields;
volatile Field[] publicFields;
volatile Method[] declaredMethods;
volatile Method[] publicMethods;
volatile Constructor[] declaredConstructors;
volatile Constructor[] publicConstructors;
// Intermediate results for getFields and getMethods
volatile Field[] declaredPublicFields;
volatile Method[] declaredPublicMethods;
volatile Class
// Cached names
String simpleName;
String canonicalName;
static final String NULL_SENTINEL = new String();
// Value of classRedefinedCount when we created this ReflectionDat聂鑫怎样强撑的一年半a instance
final int redefinedCount;
}

能够看到,保存了 Class 中的特点和办法。 假如缓存为空,就会经过 getDeclaredMethods0 从 JVM 中查找办法。

getDeclaredMethods0 是一个 native 办法,这儿暂时先不看。

经过上面几个过程,就获取到 Method 数组。

这便是 getMethod 方倒挂姐法的整个完成了。

咱们再回过头看一下 getDeclaredMethod 办法的完成,经过 privateGetDeclaredMethods 获取办法今后,会经过 searchMethods 对办法进行挑选。

public Method getDeclaredMethod(String name, Class

throws NoSuchMethodException, SecurityException {

// ...

Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);

// ...

}

searchMethods 办法完成比较简略,便是比照办法名,参数,办法回来值。

class Class {
private static Method searchMethods(Method[] methods,
String name,
Class
{
ReflectionFactory fact = getReflectionFactory();
Method res = null;
for (Method m : methods) {
// 比较办法名
if (m.getName().equals(name)
// 比较办法参数
&& arrayContentsEq(parameterTypes,
fact.getExecutableSharedParameterTypes(m))
// 比较回来值
&& (res == null
|| (res.getReturnType() != m.getReturnType()
&& res.getReturnType().isAssignableFrom(m.getReturnType()))))
res = m;
}
return res;
}
}

1.3.5 Method#copy

在获取到对应办法今后,并不会直接回来,而是会经过 getReflectionFactory().copyMethod(method); 回来办法的一个复制。

终究调用的是 Method#copy,咱们来看看其完成。

class Method {

Method copy() {

// This routine enables sharing of MethodAccessor objects

// among Method objects which refer to the same underlying

// method in the VM. (All of this contortion is only necessary

// because of the "accessibility" bit in AccessibleObject,

// which implicitly requires that new java.lang.reflect

// objects be fabricated for each reflective call on Class

// objects.)

if (this.root != null)

throw new IllegalArgumentException("Can not copy a non-root Method");

Method res = n黄岛气候,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版ew Method(clazz, name, parameterTypes, returnType,

exceptionTypes, modifiers, slot, signature,

annotations, parameterAnnotations, annotationDefault);

res.root = this;

// Might as well eagerly propagate this if already present

res.methodAccessor = methodAccessor;

return res;

}

}

会 new 一个 Method 实例并回来。

这儿有两点要注意:

  1. 设置 root = this
  2. 会给 Method 设置 MethodAccessor,用于后边办法调用。也便是一切的 Method 的复制都会运用同一份 methodAccessor。

经过上面的过程,就获取到了需求反射的办法。

咱们再回忆一下之前的流程。

二、Java 反射原理--调用反射办法

获取到办法今后,经过 Method#invoke 调用办法。

class Method {

public Object invoke(Object obj, Object... args)

throws IllegalAccessException, IllegalArgumentException,

InvocationTargetException

{

if (!override) {

Class

// 1. 查看权限

checkAccess(caller, clazz,

Modifier.isStatic(modifiers) ? null : obj.getClass(),

modifiers);

}

// 2. 获取 MethodAccessor

MethodAccessor ma = methodAccessor; // read vo同人h文latile

if (ma == null) {

// 创立 MethodAccessor

ma = acquireMethodAccessor();

}

// 3黄岛气候,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版. 调用 MethodAccessor.invoke

return ma.invoke(obj, args);

}

}

invoke 办法的完成,分为三步:

2.1 查看是否有权限调用办法

这儿对 override 变量进行判别,假如 override == true,就越过查看 咱们通常在 Method#invoke 之前,会调用 Method#setAccessible(true),便是设置 override 值为 true。

2.2 获取 MethodAccessor

在上面获取 Method 的时分咱们讲到过,Method#copy 会给 Method 的 me草避图rthodAccessor 赋值。所以这儿的 methodAccessor 便是复制时运用的 MethodAccessor。

假如 ma 为空,就去创立 MethodAccessor。

class Method {

private MethodAccessor acquireMethodAccessor() {

// First check to see if one has been created yet, and take it

// if so

MethodAccessor tmp = null;

if (root != null) tmp = root.getMethodAccessor();

if (tmp != null) {

methodAccessor = tmp;

} else {

// Otherwise fabricate one and propagate it up to the root

tmp = reflectionFactory.newMethodAccessor(this);

setMethodAccessor(tmp);

}

return tmp;

}

}

这儿会先查找 root 的 MethodAccessor,这儿的 root 在上面 Method#copy 中设置过。

假如仍是没有找到,就去创立 MethodAccessor。

class ReflectionFactory {
public MethodAccessor newMethodAccessor(Method method) {
// 其间会对 noInflation 进行赋值
checkInitted();
// ...
if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
// 生成的是 MethodAccessorImpl
return new MethodAccessorGenerator().
generateMethod(method.getDeclaringClass(),
method.getName(),
method.getParameterTypes(),
method.getReturnType(),
method.getExceptionTypes(),
method.getModifiers());
} else {
NativeMethodAccessorImpl acc =
new NativeMethodAccessorImpl(method);
DelegatingMethodAccessorImpl res =
new DelegatingMethodAccessorImpl(acc);
acc.setParent(res);
return res;
}
}
}

这儿能够看到,一共有三种 MethodAccessor。MethodAccessorImpl,NativeMethodAccessorImpl,DelegatingMethodAccessorImpl。

选用哪种 MethodAccessor 依据 noInflation 进行判别,noInflation 默许值为 false,只要指定了 sun.reflect.noInflation 特点为 true,才会 选用 MethodAccessorImpl。

所以默许会调用 NativeMethodAccessorImpl。

MethodAccessorImpl 是经过动态生成字节码来进行办法调用的,是 Java 版别的 MethodAccessor,字节码生成比较复杂,这儿不放代码了。咱们感兴趣能够看这儿的 generate 办法。

DelegatingMethodAccessorImpl 便是单纯的署理,真实的完成仍是 NativeMethodAccessorImpl。

class DelegatingMethodAccessorImpl extends MethodAccessorImpl {

private MethodAccessorImpl delegate;

DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) {

setDelegate(delegate);

}

public Object invoke(Object obj, Object[] args)

throws IllegalArgumentException, InvocationTargetException

{

return delegate.invoke(obj, args);

}

void setDelegate(MethodAccessorImpl delegate) {

this.delegate = delegate;

}

}

NativeMethodAccessorImpl 是 Native 版别的 MethodAccessor 完成。

class NativeMethodAccessorImpl extends MethodAccessorImpl {

public Object invoke(Object obj, Obje问天阙ct[] args)

throws IllegalArgumentException, InvocationTargetException

{

// We can't inflate methods belonging to vm-anonymous classes because

// that kind of class can't be referred to by name, hence can't be

// found from the generated bytecode.

if (++numInvocations > ReflectionFactory.inflationThreshold()

&& !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {

// Java 版别的 MethodAccessor

MethodAccessorImpl acc = (MethodAccessorImpl)

new MethodAccessorGenerator().

generateMethod(method.getDeclaringClass(),

method.getName(),

method.getParameterTypes(),

method.getReturnType(),

method.getExceptionTypes(),

method.getModifiers());

parent.setDelegate(acc);

}

// Native 版别调用

return invoke0(method, obj, args);

}

private static nativ黄岛气候,气,飞天小说-雷竞技app_raybet雷竞技app_雷竞技app苹果版e Object invoke0(Method m, Object obj, Object[] args);

}

在 NativeMethodAccessorImpl 的完成中,咱们能够看到,有一个 numInvocations 阀值操控,numInvocations 表明调用次数。假如 numInvocations 大于 15(默许阀值是 15),那么就运用 Java 版别的 MethodAccessorImpl。

为什么选用这个战略呢,能够 JDK 中的注释:

 // "Inflation" mechanism. Loading bytecodes to implement
// Method.invoke() and Constructor.newInstance() currently costs
// 3-4x more than an invocation via native code for the first
// invocation (though subsequent invocations have been benchmarked
// to be over 2广银融投0x faster). Unfortunately this cost increases
// startup time for certain applications that use reflection
// intensively (but only once per class) to bootstrap themselves.
// To avoid this penalty we reuse the existing JVM entry points
// for the first few invocations of Methods and Constructors and
// then switch to the bytecode-based implementations.
//
// Package-private to be accessible to NativeMethodAccessorImpl
// and NativeConstructorAccessorImpl
private static boolean noInflation = false;

Java 版别的 MethodAccessorImpl 调用功率比 Native 版别要快 20 倍以上,可是 Java 版别加载时要比 Native 多耗费 3-4 倍资源,所以默许会调用 Native 版别,假如调用次数超越 15 次今后,就会挑选运转功率更高的 Java 版别。

那为什么 Native 版别运转功率会没有 Java 版别高呢?从 R 大博客来看,是由于 这是HotSpot的优化办法带来的功能特性,一起也是许多虚拟机的共同点:跨过native鸿沟会对优化有阻止效果,它就像个黑箱相同让虚拟机难以剖析也将其内联,所以运转时间长了之后反而是保管版别的代码更快些

2.3 调用 MethodAccessor#invoke 完成办法的调用

在生成 MethodAccessor 今后,就调用其 invoke 办法进行终究的反射调用。

这儿咱们对 Java 版别的 MethodAccessorImp陆道长很忙l 收吧收吧名车广场做个简略的剖析,Native 版别暂时不做剖析。

在前面咱们说到过 MethodAccessorImpl 是经过 MethodAccessorGenerator#generate 生成动态字节码然后动态加载到 JVM 中的。

其间生成 invoke 办法字节码的是 MethodAccessorGenerator#emitInvoke。

咱们看其间校验参数的一小段代码:

// Iterate through incoming actual parameters, ensuring that each

// is compatible with the formal parameter type, and pushing the

// actual on the operand stack (unboxing and widening if necessary).

// num args of other invoke bytecodes

for (int i = 0; i < parameterTypes.length; i++) {

// ...

if (isPrimitive(paramType)) {

// Unboxing code.

// Put parameter into temporary local variable

// astore_3 | astore_2

// ...

// repeat for all possible widening conversions:

// aload_3 | aload_2

// instanceof

// ifeq

// alo国家为什么操控磁动机ad_3 | aload_2

// checkcast // Note: this is "redundant",

// // but necessary for the verifier

// invokevirtual

//

// goto

// ...

// last unboxing label:

// new

// dup

// invokespecial

// athrow

}

}

经过上面的注释以及字节码,咱们能够看到,生成的 invoke 办法,会对传入的参数做校验,其间会触及到 unboxing 操作。

到此,根本上 Java 办法反射的原理就介绍完了。

三、Java 反射功率低的原因

了解了反射的原理今后,咱们来剖析一下反射功率低的原因。

1. Method#invoke 办法会对参数做封装和解封操作

咱们能够看到,invoke 办法的参数是 Object[] 类型,也便是说,假如办法参数是简略类型的话,需求在此转化成 Object 类型,例如 long ,在 javac compile 的时分 用了Long.valueOf() 转型,也就大量了生成了Long 的 Object, 一起 传入的参数是Object[]数值,那还需求额定封装object数组。

而在上面 MethodAccessorGenerator#emitInvoke 办法里咱们看到,生成的字节码时,会把参数数组拆解开来,把参数康复到没有被 Object[] 包装前的姿态,一起还要对参数做校验,这儿就触及到了解封操作。

因而,在反射调用的时分,由于封装和解封,产生了额定的不必要的内存糟蹋,当调用次数到达一定量的时分,还会导致 GC。

2. 需求查看办法可见性

经过上面的源码剖析,咱们会发现,反射时每次调用都有必要查看办法的可见性(在 Method.invoke 里)

3. 需求校验参数

反射时也有必要查看每个实践参数与形式参数的类型匹配性(在NativeMethodAccessorImpl.invoke0 里或许生成的 Java 版 MethodAccessor.invoke 里);

4. 反射办法难以内联

Method#invoke 就像是个独木桥相同,遍地的反射调用都要挤过去,在调用点上收集到的类型信息就会很乱,影响内联程序的判别,使得 Method.invoke() 本身难以被内联到调用方。拜见 www.iteye.com/blog/rednax…

5. JIT 无法优化

在 JavaDoc 中说到:

Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

由于反射触及到动态加载的类型,所以无法进行优化。

总结

上面便是对反射原理和反射功率低的一些剖析。

作者:ZYLAB 来历:掘金

链接:https://juejin.im/post/5da33b2351882509334fc0d3

重视我,私信回复“材料”获取面试宝典《Java中心常识点收拾.pdf》“,覆盖了JVM、锁、高并发、反射、Spring原理