Java 反射性能瓶颈分析
反射机制虽然灵活,但其性能开销一直是开发者关注的焦点。很多人知道反射慢,但具体慢在哪里、影响程度如何,往往缺乏实证数据支撑。为了搞清楚这个问题,我们设计了一组对比测试,从方法调用和字段访问两个维度,量化直接调用与反射调用的差异。
测试方案设计
为了放大差异并找到共性,我们采用了逐步增加测试次数、多次取平均值的方式。针对同一个方法,分别测试直接调用、反射调用、直接访问实例、反射访问实例四种场景,测试范围从 1 次到 100 万次,每隔一个数量级记录一次耗时。
测试代码基于 Android Activity 环境编写(核心逻辑为纯 Java),主要包含以下四个耗时统计方法:
public class ReflectionPerformanceActivity extends Activity {
private TextView mExecuteResultTxtView = null;
private EditText mExecuteCountEditTxt = null;
private Executor mPerformanceExecutor = Executors.newSingleThreadExecutor();
private static final int AVERAGE_COUNT = 10;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reflection_performance_layout);
mExecuteResultTxtView = (TextView) findViewById(R.id.executeResultTxtId);
mExecuteCountEditTxt = (EditText) findViewById(R.id.executeCountEditTxtId);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.executeBtnId:
execute();
;
:
;
}
}
{
mExecuteResultTxtView.setText();
mPerformanceExecutor.execute( () {
{
;
Integer.parseInt(mExecuteCountEditTxt.getText().toString());
, normalMethodCostTime = ;
, normalFieldCostTime = ;
updateResultTextView(executeCount + );
( ; index < AVERAGE_COUNT; index++) {
updateResultTextView( + (index + ) + );
costTime = getNormalCallCostTime(executeCount);
normalMethodCostTime += costTime;
updateResultTextView( + costTime + );
costTime = getReflectCallMethodCostTime(executeCount);
reflectMethodCostTime += costTime;
updateResultTextView( + costTime + );
costTime = getNormalFieldCostTime(executeCount);
normalFieldCostTime += costTime;
updateResultTextView( + costTime + );
costTime = getReflectCallFieldCostTime(executeCount);
reflectFieldCostTime += costTime;
updateResultTextView( + costTime + );
}
updateResultTextView( + normalMethodCostTime / AVERAGE_COUNT + );
updateResultTextView( + reflectMethodCostTime / AVERAGE_COUNT + );
updateResultTextView( + normalFieldCostTime / AVERAGE_COUNT + );
updateResultTextView( + reflectFieldCostTime / AVERAGE_COUNT + );
}
});
}
{
System.currentTimeMillis();
( ; index < count; index++) {
(, , );
{
programMonkey.getClass().getMethod(, String.class);
setmLanguageMethod.setAccessible();
setmLanguageMethod.invoke(programMonkey, );
} (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
}
System.currentTimeMillis() - startTime;
}
{
System.currentTimeMillis();
( ; index < count; index++) {
(, , );
{
programMonkey.getClass().getDeclaredField();
ageField.set(programMonkey, );
} (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
System.currentTimeMillis() - startTime;
}
{
System.currentTimeMillis();
( ; index < count; index++) {
(, , );
programMonkey.setmLanguage();
}
System.currentTimeMillis() - startTime;
}
{
System.currentTimeMillis();
( ; index < count; index++) {
(, , );
programMonkey.mLanguage = ;
}
System.currentTimeMillis() - startTime;
}
{
ReflectionPerformanceActivity..runOnUiThread( () {
{
mExecuteResultTxtView.append(content);
mExecuteResultTxtView.append();
}
});
}
}




