有一段時間沒有寫blog了,主要緣由是前段時間去西安旅遊了。好了進入正題。這個篇blog將學習到如何生成一個Class。而且在這個Class中添加局部變量和各類類型的方法。java
首先咱們看下要生成的class對應的java代碼是什麼:web
<!-- lang: java --> public class CreateClassExample { private static String staticGlobalVariable = "I'm a static global variable at class"; public int globalVariable; public CreateClassExample(int intVal) { this.globalVariable = intVal; } private void commonMethod() { System.out.println("staticGlobalVariable : " + staticGlobalVariable); System.out.println("globalVariable : " + this.globalVariable); } public static void main(String[] args) { new CreateClassExample(1024).commonMethod(); } }
和前面的例子同樣咱們建立一個帶有main方法的可執行的class數組
<!-- lang: java --> public class CreateClass extends AbstractExample { public static void main(String[] args) throws Exception{ //asmsupport code generate(creator); } }
咱們的生成class的代碼寫在上面的"//asmsupport code"處,具體代碼以下:app
<!-- lang: java --> public class CreateClass extends AbstractExample { public static void main(String[] args) throws Exception, NoSuchMethodException { ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC , "generated.create.CreateClassExample", null, null); creator.createGlobalVariable("staticGlobalVariable", Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, AClass.STRING_ACLASS); creator.createStaticBlock(new CInitBody(){ @Override public void generateBody() { assign(getMethodOwner().getGlobalVariable("staticGlobalVariable"), Value.value("I'm a static global variable at class")); runReturn(); } }); creator.createGlobalVariable("globalVariable", Opcodes.ACC_PUBLIC, AClass.INT_ACLASS); creator.createConstructor(new AClass[]{AClassFactory.getProductClass(int.class)}, new String[]{"intVal"}, new InitBody(){ @Override public void generateBody(LocalVariable... argus) { invokeSuperConstructor(); assign(getThis().getGlobalVariable("globalVariable"), argus[0]); runReturn(); } }, Opcodes.ACC_PUBLIC); creator.createMethod("commonMethod", null, null, null, null, Opcodes.ACC_PRIVATE, new CommonMethodBody(){ @Override public void generateBody(LocalVariable... argus) { invoke(systemOut, "println", append(Value.value("staticGlobalVariable : "), getMethodOwner().getGlobalVariable("staticGlobalVariable"))); invoke(systemOut, "println", append(Value.value("globalVariable : "), getThis().getGlobalVariable("globalVariable"))); runReturn(); } }); creator.createStaticMethod("main", new AClass[]{AClassFactory.getProductClass(String[].class)}, new String[]{"args"}, null, null, Opcodes.ACC_PUBLIC, new StaticMethodBody(){ @Override public void generateBody(LocalVariable... argus) { invoke(invokeConstructor(getMethodOwner(), Value.value(1024)), "commonMethod"); runReturn(); } }); generate(creator); } }
下面咱們對每一句代碼進行解釋:jvm
<!-- lang: java --> ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC , "generated.create.CreateClassExample", null, null);
這代碼的做用就是建立一個Class建立器,經過上面的代碼建立了一個"public class generated.create.CreateClassExample",jdk版本是1.5的class。構造它須要5個參數,依次是:ide
<!-- lang: java --> creator.createGlobalVariable("staticGlobalVariable", Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, AClass.STRING_ACLASS);
這部分是建立一個靜態全局 變量。基本和上篇博客CreateInterface.java(http://my.oschina.net/wensiqun/blog/117708)中如何建立和賦值是同樣的,惟一不一樣的是這時候全局變量的修飾符,和ClassCreator的modifiers相似,例如: Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC。svn
<!-- lang: java --> creator.createStaticBlock(new CInitBody(){ @Override public void generateBody() { assign(getMethodOwner().getGlobalVariable("staticGlobalVariable"), Value.value("I'm a static global variable at class")); runReturn(); } });
這裏是建立一個靜態語句塊,在靜態語句塊中爲全局static變量賦值。和上一篇blog中的靜態變量賦值是同樣的。函數
<!-- lang: java --> creator.createGlobalVariable("globalVariable", Opcodes.ACC_PUBLIC,AClass.INT_ACLASS);
建立個非靜態的全局變量,咱們這裏僅僅值作一個全局變量的聲明。咱們並不能在這裏給予它賦值。這裏得區別於咱們平時編寫java代碼,其實若是你對java字節碼熟悉的話也能知道,在java字節碼中,全局變量的賦值是在static塊中或者構造方法中實現的,前者是給靜態的全局變量賦值。然後者是給非靜態的變量賦值。咱們這裏也同樣。若是是static的全局變量咱們將在createStaticBlock中賦值,不然咱們在createConstructor中賦值。學習
<!-- lang: java --> creator.createConstructor(new AClass[]{AClassFactory.getProductClass(int.class)}, new String[]{"intVal"}, new InitBody(){ @Override public void generateBody(LocalVariable... argus) { invokeSuperConstructor(); assign(getThis().getGlobalVariable("globalVariable"), argus[0]); runReturn(); } });
建立一個構造方法,對於ClassCreator來講。若是沒有建立任何構造方法,也就是沒有調用createConstructor方法,將會自動建立一個無參的默認構造函數。咱們這裏建立的構造方法有一個int類型參數,在構造函數中將該參數賦值給咱們上面建立的globalVariable。相似生成以下的java代碼:this
<!-- lang: java --> public CreateClassExample(String intVal){ this.globalVariable = intVal; }
createConstructor方法有四個參數依次是:
這裏當咱們調用createConstructor所使用的方法體是InitBody。下面介紹InitBody裏面的內容
首先咱們看下咱們在建立匿名類InitBody的時候所重寫的方法:
<!-- lang: java --> public void generateBody(LocalVariable... argus) {....}
這個方法中的內容就是咱們建立的構造方法裏面須要執行的內容了,他有一個變元參數 argus。這裏的參數表示的是咱們當前建立的構造方法的參數。這個數組中每一個LocalVariable和createConstructor方法的第一個參數中的AClass數組一一對應的。例如這裏argus只有一個元素它的類型是int類型,名字是intVal。
<!-- lang: java --> invokeSuperConstructor();
這裏要注意的。 要顯示的調用invokeSuperConstructor,他的做用就是等同於咱們編寫java代碼的時候調用super()同樣。只不過咱們在用java建立個構造函數的時候有時候不須要調用super,是應爲父類的存在沒有參數的構造方法。但這並不代碼jvm沒有去調用super().其實編譯器在編譯java的時候已經將調用super的指令加上到了構造方法的字節碼中去了。這個方法存在一個變元參數arguments。他表示咱們調用super()的時候須要傳遞的參數,因爲咱們建立的class沒有繼承任何類即只繼承了Object類,那麼咱們就不須要傳遞參數直接調用invokeSuperConstructor();
<!-- lang: java --> assign(getThis().getGlobalVariable("globalVariable"), argus[0]);
因爲咱們建立的globalVariable是非static的。因此經過getThis()獲取globalVariable。getThis()對應於java代碼中就是this關鍵字。
<!-- lang: java --> creator.createMethod("commonMethod", null, null, null, null, Opcodes.ACC_PRIVATE, new CommonMethodBody(){ @Override public void generateBody(LocalVariable... argus) { invoke(systemOut, "println", append(Value.value("staticGlobalVariable : "), getMethodOwner().getGlobalVariable("staticGlobalVariable"))); invoke(systemOut, "println", append(Value.value("globalVariable : "), getThis().getGlobalVariable("globalVariable"))); runReturn(); } });
建立一個private的commonMethod方法。在commonMethod中將打印出staticGlobalVariable和globalVariable的值。對應的java代碼以下:
<!-- lang: java --> private void commonMethod(){ System.out.println("staticGlobalVariable : " + staticGlobalVariable); System.out.println("globalVariable : " + globalVariable); }
<!-- lang: java --> creator.createStaticMethod("main", new AClass[]{AClassFactory.getProductClass(String[].class)}, new String[]{"args"}, null, null, Opcodes.ACC_PUBLIC, new StaticMethodBody(){ @Override public void generateBody(LocalVariable... argus) { invoke(invokeConstructor(getMethodOwner(), Value.value(1024)), "commonMethod"); runReturn(); } });
這裏咱們建立一個咱們常常用到的靜態方法main方法,在這個方法中咱們首先new一個咱們正在建立的class而後調用它的commonMethod方法。對應的java代碼以下:
<!-- lang: java --> public static void main(String[] args){ new CreateClassExample(1024).commonMethod(); }
好了運行代碼能夠看到控制檯輸出:
staticGlobalVariable : I'm a static global variable at class
globalVariable : 1024
資源地址
ASMSupport項目地址:http://www.oschina.net/p/amssupport
ASMSupport源碼地址:https://amssupport.googlecode.com/svn/trunk/ ASMSupport實例地址:http://amssupport.googlecode.com/svn/trunk/asmsupport/src/test/java/example/
本文示例地址:
AbstractExample: http://amssupport.googlecode.com/svn/trunk/asmsupport/src/test/java/example/AbstractExample.java
CreateInterface: http://amssupport.googlecode.com/svn/trunk/asmsupport/src/test/java/example/create/CreateClass.java
以上代碼都可經過svn下載
最新asmsupport下載地址:https://amssupport.googlecode.com/files/asmsupport-0.2-alpha-2013-03-25.jar