| \u001B[1mSYNOPSIS\u001B[0m |
| ${project.description} |
| |
| Original Maven URL: |
| \u001B[33mmvn:${pkgGroupId}/${pkgArtifactId}/${pkgVersion}\u001B[0m |
| |
| \u001B[1mDESCRIPTION\u001B[0m |
| Serp is an open source framework for manipulating Java bytecode. |
| |
| Bytecode manipulation is a powerful tool in the arsenal of the Java developer. It can be used for tasks from |
| compiling alternative programming languages to run in a JVM, to creating new classes on the fly at runtime, to |
| instrumenting classes for performance analysis, to debugging, to altering or enhancing the capabilities of existing |
| compiled classes. Traditionally, however, this power has come at a price: modifying bytecode has required an |
| in-depth knowledge of the class file structure and has necessitated very low-level programming techniques. |
| These costs have proven too much for most developers, and bytecode manipulation has been largely ignored by the |
| mainstream. |
| |
| The goal of the serp bytecode framework is to tap the full power of bytecode modification while lowering its |
| associated costs. The framework provides a set of high-level APIs for manipulating all aspects of bytecode, from |
| large-scale structures like class member fields to the individual instructions that comprise the code of methods. |
| While in order to perform any advanced manipulation, some understanding of the class file format and especially |
| of the JVM instruction set is necessary, the framework makes it as easy as possible to enter the world of bytecode |
| development. |
| |
| There are several other excellent bytecode frameworks available. Serp excels, however, in the following areas: |
| |
| * Ease of use. Serp provides very high-level APIs for all normal bytecode modification functionality. |
| Additionally, the framework contains a large set of convenience methods to make code that uses it as clean |
| as possible. From overloading its methods to prevent you from having to make type conversions, to making |
| shortcuts for operations like adding default constructors, serp tries to take the pain out of bytecode |
| development. |
| * Power. Serp does not hide any of the power of bytecode manipulation behind a limited set of high-level |
| functions. In addition to its available high-level APIs, which themselves cover the functionality all but |
| the most advanced users will ever need, serp gives you direct access to the low-level details of the class |
| file and constant pool. You can even switch back and forth between low-level and high-level operations; serp |
| maintains complete consistency of the class structure at all times. A change to a method descriptor in the |
| constant pool, for example, will immediately change the return values of all the high-level APIs that describe |
| that method. |
| * Constant pool management. In the class file format, all constant values are stored in a constant pool of |
| shared entries to minimize the size of class structures. Serp gives you access to the constant pool directly, |
| but most of you will never use it; serp's high-level APIs completely abstract management of the constant pool. |
| Any time a new constant is needed, serp will automatically add it to the pool while ensuring that no |
| duplicates ever exist. Serp also does its best to manipulate the pool so that the effects of changing a |
| constant are as expected: i.e. changing one instruction to use the string "bar" instead of "foo" will not |
| affect other instructions that use the string "foo", but changing the name of a member field will instantly |
| change all instructions that reference that field to use the new name. |
| * Instruction morphing. Dealing with the individual instructions that make up method code is the most difficult |
| part of bytecode manipulation. To facilitate this process, most serp instruction representations have the |
| ability to change their underlying low-level opcodes on the fly as the you modify the parameters of the |
| instruction. For example, accessing the constant integer value 0 requires the opcode iconst0, while accessing |
| the string constant "foo" requires a different opcode, ldc, followed by the constant pool index of "foo". |
| In serp, however, there is only one instruction, constant. This instruction has setValue methods which use |
| the given value to automatically determine the correct opcodes and arguments -- iconst0 for a value of 0 and |
| ldc plus the proper constant pool index for the value of "foo". |
| |
| Serp is not ideally suited to all applications. Here are a few disadvantages of serp: |
| |
| * Speed. Serp is not built for speed. Though there are plans for performing incremental parsing, serp currently |
| fully parses class files when a class is loaded, which is a slow process. Also, serp's insistence on full-time |
| consistency between the low and high-level class structures slows down both access and mutator methods. |
| These factors are less of a concern, though, when creating new classes at runtime (rather than modifying |
| existing code), or when using serp as part of the compilation process. Serp excels in both of these scenarios. |
| * Memory. Serp's high-level structures for representing class bytecode are very memory-hungry. |
| * Multi-threaded modifications. The serp toolkit is not threadsafe. Multiple threads cannot safely make |
| modifications to the same classes the same time. |
| * Project-level modifications. Changes made in one class in a serp project are not yet automatically propogated |
| to other classes. However, there are plans to implement this, as well as plans to allow operations to modify |
| bytecode based on specified patterns, similar to aspect-oriented programming. |
| |
| The first step to using bytecode modification is to get familiar with the inner workings of class files. |
| The class file format is covered here. Advanced manipulation involving changing or creating methods requires |
| knowledge of the JVM instruction set, outlined here. Finally, learn to use the javap standard Java tool. |
| Running javap -c on any class name will show you the opcodes of the class' methods -- this gives you an unlimited |
| supply of examples to work from when writing your own opcodes. |
| |
| The first class you should study in the serp bytecode toolkit is the serp.bytecode.Project type. From there, |
| move onto the serp.bytecode.BCClass, and trace its APIs into serp.bytecode.BCField, serp.bytecode.BCMethod, and |
| finally into actual serp.bytecode.Code. |
| |
| \u001B[1mSEE ALSO\u001B[0m |
| \u001B[36mhttp://serp.sourceforge.net/\u001B[0m |