About the Author
Xue Guyu, Nordsan (Beijing) Information Technology Development Co., Ltd. Advanced Java R & D Engineer, is committed to the development of server products for enterprise heterogeneous data exchange, has a relatively rich development experience in J2EE and Web Service, you can pass Rainight @ 126.com Contact him.
Foreword
Code generator, cg), as the name referway is a tool for generating code. With it, you can get a few hundred and thousand lines of code from a simple setting or database design. If this technology is not used, developers have to spend a few hours or time to manually write these code. On the other hand, excellent development tools are often provided with code generation technology to provide a programmatic template frame for users, and their purpose is to improve programming efficiency. The above view is only a general understanding of the code generator. In other words, this seems to be a could have no things, without it, but it is more labor. However, this article is not as small in this article, the function of the Java tool class named, which can generate a Java bytecode, which is the Class file. You can generate a variety of CLASS based on the situation in the application, then call, reach a magical magic of nearly God. The heart is not as good as action. If you want to introduce this advanced programming technology in your own development, please see this article.
Small and magical ASM
ASM is a set of Java bytecode generation architecture. It can dynamically generate the STUB class or other proxy class of binary format, or dynamically modify the class before the class is loaded by the Java virtual machine. ASM provides a function similar to BCEL (http://jakarta.apache.org/bcel) and serp (http://serp.sourceforge.net/), only 22K size, compared to 350K BCEL and 150K SERP It is quite small, and it has higher execution efficiency, 7 times the BCEL, more than 11 times the SERP. ASM has consistent design idea is to apply it to dynamic build fields, so small and shortcuts have always been guiding ideas for this product.
This product is responsible for the R & D engineer of French Telecom. Since the first version of ASM in July 2002, this product has been upgraded five times, and it is perfect. So far, the latest version of ASM is 1.3.5, you can go to http://asm.ObjectWeb.org/ download.
The ultimate goal of ASM is to create a generating tool that can be used to perform processing operations for any class (unlike some tools, such as Javassit, which only support pre-defined class operations, but this function is limited in many occasions of).
Java's Class file format
To drive the ASM, let's take a look at the Java's Class file format. Java's Class file is usually a tree structure. The root node contains the following elements:
ConstantPool: Symbol Table; FieldInfo: Member Variable Information in Class; MethodInfo: Method Description in Class; Attribute: An optional additional node.
The FieldInfo node contains the name of the member variable, such as the flag of public, private, static, and so on. The ConstantValue property is used to store the value of the static constant member variable. DepRecated and Synthetic are used to mark a member variable is not recommended or generated by the compiler.
The methodinfo node contains the name of the method, the type of parameter, and its return value, the method is public, private or static. MethodInfo contains an optional additional property, which is the most important thing that the Code property contains the code of non-abstract methods. The Exceptions property contains the name of the Exception that will thrown. The information of deprecated and synthetic properties is the same as the definition of the above FieldInfo. Optional properties of the root node are SourceFile, InnerClasses, and DepRecated. SourceFile is used to store the original name of the source code file that is compiled into one bytecode; InnerClasses stores the internal class information. Due to these attributes, Java's class format is scalable, that is, can attach some non-standard properties in a class, Java virtual opportunity ignores these unrecognizable properties, and properly load this Class.
ConstantPool is a queue consisting of a queue consisting of an index of numbers or string constants, or a queue that is referenced by other nodes of this type of trees that are created by other objects. The goal of this table is to reduce redundancy. For example, the FieldInfo node does not include the name of the node, only the index it in this table. Similarly, getField and Putfield do not directly contain the name of the member variable, only the index of the name.
Proficient in ASM
The ASM architecture is entirely around two interfaces, which is Classvisitor and Codevisitor, which can access the method of each class, member variable, which is included in the bytecode instruction in each method. ClassReader is used to read the class file; the classwriter class is used to write the generated Class file.
To modify the existing Class, you must use the ClassReader, classes of the Class file, and the ClassWriter written in the Class file. Class fixtures are a Classvisitor that can delegate one of the other Classvisitor, but in order to implement the expected modification step, it will change the value of some parameters, or call some other methods. In order to easily implement this type of corrector, ASM provides a ClassADAPTER and CodeAdapter, which implements the Classvistor and Codevistor interfaces, respectively.
HelloWorld, experienced magic
Below is a class that applies ASM dynamically generated bytecode, and calls the complete HelloWorld program of the method. The functionality of the program is dynamically generating an example.class class, and instantiates an Example object, call the object's main function, on the screen Print "Hello World!"
Import Org.ObjectWeb.asm. *;
Import java.lang.reflect. *;
Import java.io.fileoutputstream;
Public Class HelloWorld Extends ClassLoader IMPLEments Constants {
Public static void main (final string args [] throws exception {
/ *
* This program will generate a Class, the corresponding Java source code is:
*
* public class example {
* public static void main (string [] args) {
* System.out.println ("Hello World!");
*}
*}
*
* /
// Create a ClassWriter
Classwriter CW = New ClassWriter (FALSE);
CW.visit (ACC_PUBLIC, "EXAMPLE", "Java / Lang / Object", NULL, NULL); // Create a MethodWriter
Codevisitor MW = CW.Visitmethod (ACC_PUBLIC, "
"," () V ", null;
// Push 'THIS' variable
Mw.visitvarinsn (ALOAD, 0);
// Create a constructor of the parent class
Mw.visitmethodinsn (InvokeSpecial, "Java / Lang / Object", "
"," () V ");
Mw.visitinsn;
// This code uses up to one stack element and a local variable
Mw.visitmaxs (1, 1);
/ / Create a MethodWriter for the main method
MW = cw.visitmethod
ACC_PUBLIC ACC_STATIC, "Main", "([Ljava / Lang / String;) V", NULL);
// Use the System class OUT member class
Mw.visitfieldinsn
GetStatic, "Java / Lang / System", "OUT", "Ljava / IO / PrintStream;");
// pushes the "Hello World!" String Constant
Mw.visitldcinsn ("Hello World!");
// Call the 'Println' function of System.out
Mw.visitmethodinsn
Invokevirtual, "Java / IO / PrintStream", "Println", "(Ljava / Lang / String;) V");
Mw.visitinsn;
// This code uses up to two stack elements and two local variables
Mw.visitmaxs (2, 2);
/ / Class in the form of a word code code
Byte [] code = cw.tobytearray ();
FileOutputStream Fos = New FileOutputStream ("eXample.class");
// write file
Fos.Write (Code);
// Turn off output flow
Fos.close ();
/ / Institute instantiate the class that has just been generated
HelloWorld Loader = New HelloWorld ();
Class ExampleClass = loader.defineclass ("eXample", code, 0, code.length;
// Print 'HelloWorld' using dynamically generated classes
Method main = esampleclass.getMethods () [0];
Main.invoke (NULL, New Object [] {null});
}
}