疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java反射机制的效率


 

  java的反射机制是程序能够在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法,这些特性使我们只需编写比以前少的多的代码,就可以来完成相同的功能,但是反射带来的多余的性能消耗却是我们需要关注的,性能的消耗点是哪里,这些都需要清楚。

  废话就不多说了,直接上测试数据先

  以下就是对一个set方法的普通调用,反射调用,获取set反射方法执行时间的对比

  运行环境1: cpu:intel i5-3210 2.5GHz 内存 :8G JDK1.6 x64 操作系统:win7

  再来就是测试源码了

  Java代码

  package com.example.android_test;

  Java代码

  import java.lang.reflect.InvocationTargetException;

  import java.lang.reflect.Method;

  import java.util.Date;

  Java代码

  public class Test {

  public static long times = 1000;

  public static final String str="111";

  /**

  * @param args

  * @throws InvocationTargetException

  * @throws IllegalAccessException

  * @throws NoSuchMethodException

  * @throws IllegalArgumentException

  * @throws SecurityException

  */

  public static void main(String[] args) throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {

  normal();

  reflect();

  reflectMethod();

  }

  Java代码

  /**

  * 普通方法

  */

  public static void normal() {

  Demo demo = new Demo();

  Date dateS = new Date();

  printUsedMemory();

  for (int i = 0; i < times ; i++) {

  demo.setStr(str);

  }

  printUsedMemory();

  Date dateE = new Date();

  long time = dateE.getTime() - dateS.getTime();

  System.out.println(time + "毫秒");

  }

  Java代码

  /**

  * 反射方法

  * @throws SecurityException

  * @throws NoSuchMethodException

  * @throws IllegalArgumentException

  * @throws IllegalAccessException

  * @throws InvocationTargetException

  */

  public static void reflect() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

  Demo demo = new Demo();

  Date dateS = new Date();

  Method m;

  m = Demo.class.getMethod("setStr", String.class);

  printUsedMemory();

  for (int i = 0; i < times; i++) {

  m.invoke(demo, str);

  }

  printUsedMemory();

  Date dateE = new Date();

  Java代码

  long time = dateE.getTime() - dateS.getTime();

  System.out.println(time + "毫秒");

  Java代码

  }

  /**

  * 获取反射方法

  * @throws SecurityException

  * @throws NoSuchMethodException

  * @throws IllegalArgumentException

  * @throws IllegalAccessException

  * @throws InvocationTargetException

  */

  public static void reflectMethod() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

  Demo demo = new Demo();

  Date dateS = new Date();

  Method m;

  printUsedMemory();

  for (int i = 0; i < times; i++) {

  m = Demo.class.getMethod("setStr", String.class);

  }

  printUsedMemory();

  Date dateE = new Date();

  Java代码

  long time = dateE.getTime() - dateS.getTime();

  System.out.println(time + "毫秒");

  Java代码

  }

  Java代码

  public static long printUsedMemory() {

  long totalMemory = Runtime.getRuntime().totalMemory();

  long freeMemory = Runtime.getRuntime().freeMemory();

  long usedMemory = totalMemory - freeMemory;

  System.out.println("虚拟机已用内存:" + usedMemory + " Byte|" + usedMemory / 1024 + " KB");

  return usedMemory;

  }

  }

  准备好这些,那么就开始分析数据了

  第一个分析点:普通方法和反射的数据对比,从以上两个环境的数据的平均值来看,PC的调用时间差距是4倍左右, 手机的的调用时间差距是15倍左右(平均后的数据,大概啦); 虽然有这样的差距,但是PC端在10万次的调用中,仅仅耗时53ms,在测试例子中的方法调用已经排除了对象创建的消耗,现实场景中加上多余对象操作的消耗,一秒完全可以跑完(除非里面真的写了耗时的操作),在手机端上,10万次的计算,也才815ms,实际场景中手机端一次操作进行10万次的反射调用,几乎没有!在考虑的反射带来的方便和它的性能消耗,完全可以忽略这些消耗啦!

  第二个分析点:获取反射方法,看看以上的数据,其消耗的时间是执行反射方法的10倍,随着执行次数的增加,呈几何递增啊!而在自己看来,获取反射方法就是获取类的信息,类的信息在运行时不会变化,完全没有必要重复取反射方法,可以设计一套缓存的机制,将这些类的信息缓存起来,达到提高效率的目的,这样带来的内存消耗当然是必不可少的,但是怎么把握这个平衡点就看自己了。

  第三点分析点:内存问题!使用反射比普通的调用,其实就多了反射相关对象的创建的内存消耗,不过与其带来的便利相比,是可以接受的。

  大学生提升Java技能,首选疯狂Java培训。疯狂软件学院的Java培训(疯狂软件学院http://www.fkjava.org/抢座热线:020-28309358,020-28309378咨询QQ:707552864,544627560 )强大的教师队伍倾情授课,带领学生走近编程,感受编程,热爱编程。疯狂软件学院打造名企技术经理,成为中国软件产业的中流砥柱:全真企业需求,项目小组管理,大量实操项目的训练,企业全真案例教学,四个半月掌握近8~10万代码量,达到技术经理的代码掌握量。疯狂Java课程提供大量企业项目训练,让学员掌握技能理念,更让学员提高动手实战能力,在实际项目工作中能灵活运用,学成至少相当于两年工作经验。在招聘现场上让你轻松入职名企,拿高薪。