5.1 目标
当一个java应用程序运行时,有很多需要消耗内存的因素存在,像对象、加载类、线程等。在这里只考虑程序中的对象所消耗的虚拟机堆空间,这样我们就可以利用Runtime 类的freeMemory()和totalMemory()方法。
5.2 实现
为了方便期间,我们首先添加一个类计算当前内存消耗。
然后修改Handler类的invoke()方法。class Memory { public static long used() { long total=Runtime.getRuntime().totalMemory(); long free=Runtime.getRuntime().freeMemory(); return (total-free); } }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable ...{ Object result; try ...{ System.out.print("begin method " + method.getName() + "("); for (int i = 0; args != null && i < args.length; i++) ...{ if (i > 0) System.out.print(","); System.out.print(" " + args[i].toString()); } System.out.println(" )"); long start=Memory.used(); result = method.invoke(obj, args); long end=Memory.used(); System.out.println("memory increased by "+(end-start)+"bytes"); } catch (InvocationTargetException e) ...{ throw e.getTargetException(); } catch (Exception e) ...{ throw new RuntimeException("unexpected invocation exception: " + e.getMessage()); } finally ...{ System.out.println("end method " + method.getName()); } return result; }
测试客户端代码如下:public interface MemoConsumer { public void creatArray(); public void creatHashMap(); } public class MemoConsumerImpl implements MemoConsumer { ArrayList arr=null; HashMap hash=null; public void creatArray() { arr=new ArrayList(1000); } public void creatHashMap() { hash=new HashMap(1000); } }
测试结果如下:MemoConsumer arrayMemo=(MemoConsumer)Handler.newInstance(new MemoConsumerImpl ()); arrayMemo.creatArray(); arrayMemo.creatHashMap();
结果一幕了然,可以看到,我们只需要修改invoke()方法,然后简单执行客户端调用就可以了。begin method creatArray( ) memory increased by 4400bytes end method creatArray begin method creatHashMap( ) memory increased by 4480bytes end method creatHashMap
6 结束语
AOP通过分解关注点和OOP相得益彰,使程序更加简洁易懂,通过Java语言本身提供的动态代理帮助我们很容易分解关注点,取得了较好的效果。不过测试对象必须实现接口在一定程度上限制了动态代理的使用,可以借鉴Spring中使用的CGlib来为没有实现任何接口的类创建动态代理。