In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "what are the reasons for the slow reflection of Java". Interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn what are the reasons for the slow Java reflection.
Is there really a performance problem with reflection?
Or use the demo of the previous article. In order to magnify the problem and find the commonness, we gradually expand the number of tests and take the average number of times for each test. For the same method, we directly call the method, reflection calls the method directly, the corresponding instance of the method is called directly, and the corresponding instance of reflection calling the method ranges from 1 to 1000000, every other order of magnitude:
The test code is as follows (the three classes Person, ICompany, and ProgramMonkey have been posted in the previous article):
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 ();} break; default: {} break;}} private void execute () {mExecuteResultTxtView.setText ("") MPerformanceExecutor.execute (new Runnable () {@ Override public void run () {long costTime = 0; int executeCount = Integer.parseInt (mExecuteCountEditTxt.getText (). ToString ()); long reflectMethodCostTime=0,normalMethodCostTime=0,reflectFieldCostTime=0,normalFieldCostTime=0; updateResultTextView (executeCount + "millisecond time test"); for (int index = 0; index
< AVERAGE_COUNT; index++){ updateResultTextView("第 " + (index+1) + " 次"); costTime = getNormalCallCostTime(executeCount); reflectMethodCostTime += costTime; updateResultTextView("执行直接调用方法耗时:" + costTime + " 毫秒"); costTime = getReflectCallMethodCostTime(executeCount); normalMethodCostTime += costTime; updateResultTextView("执行反射调用方法耗时:" + costTime + " 毫秒"); costTime = getNormalFieldCostTime(executeCount); reflectFieldCostTime += costTime; updateResultTextView("执行普通调用实例耗时:" + costTime + " 毫秒"); costTime = getReflectCallFieldCostTime(executeCount); normalFieldCostTime += costTime; updateResultTextView("执行反射调用实例耗时:" + costTime + " 毫秒"); } updateResultTextView("执行直接调用方法平均耗时:" + reflectMethodCostTime/AVERAGE_COUNT + " 毫秒"); updateResultTextView("执行反射调用方法平均耗时:" + normalMethodCostTime/AVERAGE_COUNT + " 毫秒"); updateResultTextView("执行普通调用实例平均耗时:" + reflectFieldCostTime/AVERAGE_COUNT + " 毫秒"); updateResultTextView("执行反射调用实例平均耗时:" + normalFieldCostTime/AVERAGE_COUNT + " 毫秒"); } }); } private long getReflectCallMethodCostTime(int count){ long startTime = System.currentTimeMillis(); for(int index = 0 ; index < count; index++){ ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12); try{ Method setmLanguageMethod = programMonkey.getClass().getMethod("setmLanguage", String.class); setmLanguageMethod.setAccessible(true); setmLanguageMethod.invoke(programMonkey, "Java"); }catch(IllegalAccessException e){ e.printStackTrace(); }catch(InvocationTargetException e){ e.printStackTrace(); }catch(NoSuchMethodException e){ e.printStackTrace(); } } return System.currentTimeMillis()-startTime; } private long getReflectCallFieldCostTime(int count){ long startTime = System.currentTimeMillis(); for(int index = 0 ; index < count; index++){ ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12); try{ Field ageField = programMonkey.getClass().getDeclaredField("mLanguage"); ageField.set(programMonkey, "Java"); }catch(NoSuchFieldException e){ e.printStackTrace(); }catch(IllegalAccessException e){ e.printStackTrace(); } } return System.currentTimeMillis()-startTime; } private long getNormalCallCostTime(int count){ long startTime = System.currentTimeMillis(); for(int index = 0 ; index < count; index++){ ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12); programMonkey.setmLanguage("Java"); } return System.currentTimeMillis()-startTime; } private long getNormalFieldCostTime(int count){ long startTime = System.currentTimeMillis(); for(int index = 0 ; index < count; index++){ ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12); programMonkey.mLanguage = "Java"; } return System.currentTimeMillis()-startTime; } private void updateResultTextView(final String content){ ReflectionPerformanceActivity.this.runOnUiThread(new Runnable(){ @Override public void run(){ mExecuteResultTxtView.append(content); mExecuteResultTxtView.append("\n"); } }); }}` 测试结果如下:Reflection performance test results
Test conclusion:
Reflection does cause performance problems
Whether the performance problem caused by reflection is serious or not has something to do with the number of uses. If the number of calls is less than 100, there is basically no difference. If the number of calls exceeds 100, the performance difference will be obvious.
Among the four access methods, the direct access to the instance is the most efficient, the second is the direct call to the method, which takes about 1.4 times as much time as the direct call to the instance, and then the reflection to access the instance, which takes about 3.75 times as much time as the direct access to the instance. The slowest way is to access the method through reflection, which is about 6.2 times more time than direct access to the instance.
How slow is the reflection?
Tracking the source code shows that there is code instantiating ProgramMonkey in all four methods, so the performance differences caused by different calling methods caused by this sentence can be excluded; the setAccessible method is called in the calling method through reflection, but this method simply sets the attribute value and does not produce significant performance differences. So the only ones that are most likely to cause performance differences are getMethod and getDeclaredField, invoke and set methods. Let's test these two sets of methods to find out where the specific slowness is.
First test the invoke and set methods, and modify the code for the getReflectCallMethodCostTime and getReflectCallFieldCostTime methods as follows:
Private long getReflectCallMethodCostTime (int count) {long startTime = System.currentTimeMillis (); ProgramMonkey programMonkey = new ProgramMonkey ("Xiaoming", "male", 12); Method setmLanguageMethod = null; try {setmLanguageMethod = programMonkey.getClass (). GetMethod ("setmLanguage", String.class); setmLanguageMethod.setAccessible (true);} catch (NoSuchMethodException e) {e.printStackTrace () } for (int index = 0; index)
< count; index++){ try{ setmLanguageMethod.invoke(programMonkey, "Java"); }catch(IllegalAccessException e){ e.printStackTrace(); }catch(InvocationTargetException e){ e.printStackTrace(); } } return System.currentTimeMillis()-startTime; } private long getReflectCallFieldCostTime(int count){ long startTime = System.currentTimeMillis(); ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12); Field ageField = null; try{ ageField = programMonkey.getClass().getDeclaredField("mLanguage"); }catch(NoSuchFieldException e){ e.printStackTrace(); } for(int index = 0 ; index < count; index++){ try{ ageField.set(programMonkey, "Java"); }catch(IllegalAccessException e){ e.printStackTrace(); } } return System.currentTimeMillis()-startTime; } 沿用上面的测试方法,测试结果如下:Invoke and set
The code that modifies the getReflectCallMethodCostTime and getReflectCallFieldCostTime methods is as follows to test getMethod and getDeclaredField:
Private long getReflectCallMethodCostTime (int count) {long startTime = System.currentTimeMillis (); ProgramMonkey programMonkey = new ProgramMonkey ("Xiaoming", "male", 12); for (int index = 0; index < count; index++) {try {Method setmLanguageMethod = programMonkey.getClass (). GetMethod ("setmLanguage", String.class);} catch (NoSuchMethodException e) {e.printStackTrace ();}} return System.currentTimeMillis ()-startTime } private long getReflectCallFieldCostTime (int count) {long startTime = System.currentTimeMillis (); ProgramMonkey programMonkey = new ProgramMonkey ("Xiaoming", "male", 12); for (int index = 0; index < count; index++) {try {Field ageField = programMonkey.getClass (). GetDeclaredField ("mLanguage");} catch (NoSuchFieldException e) {e.printStackTrace ();}} return System.currentTimeMillis ()-startTime;}
Following the above test method, the test results are as follows:
GetMethod and getDeclaredField
Test conclusion:
GetMethod and getDeclaredField methods are more time-consuming than invoke and set methods
As the order of magnitude of the test increases, the proportion of performance differences tends to be more stable.
Since the four methods tested end up calling native methods, they cannot be traced further. Personal guess should be related to operating class while the program is running, such as the need to determine whether it is safe or not. Is this allowed? Is the input correct? Can classes that need to be reflected be found in the virtual machine? It is mainly this series of judgment conditions that lead to reflection time-consuming; it may also be due to the need to use the JNI interface to call the natvie method, which leads to performance problems (see Log.java and System.out.println, both call the native method, and it is obvious that it takes time to call repeatedly).
How to avoid performance problems caused by reflection?
From the above tests, we can see that excessive use of reflection does have performance problems, but if used properly, the so-called performance problems caused by reflection will not be a problem. With regard to the impact of reflection on performance, refer to the following usage principles. There will be no obvious problems:
Don't use reflection too frequently. Heavy use of reflection can cause performance problems.
Accessing the instance directly through reflection is much faster than the access method, so access to the instance should be preferred.
At this point, I believe you have a deeper understanding of "what are the reasons for the slow reflection of Java?" you might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.