Preface
Bytecode We all know java
file compiled after the class
file, each byte code file consists of 10 sections have a fixed order; in fact, enhance the transformation of bytecode files to generate a new file has been To achieve our purpose, such as dynamic proxy, AOP
etc.; of course, it needs to be used after the enhancement, so it involves the problem of loading; before the introduction, let's take a look at what bytecode enhancement technologies are available.
Common technology
Common bytecode enhancement techniques are roughly divided into two categories: static enhancement and dynamic enhancement; the most common static enhancement is AspectJ
, which can be directly compiled and has its own syntax; dynamic enhancement includes: ASM
, Javassist
, Cglib
, Java Proxy
; A brief introduction is given below.
AspectJ
AspectJ
from Eclipse
foundations are woven into a static, compile-time is mainly used in weaving, used during this AspectJ
the acj
compiler (similar javac
) the aspect
class compiled into class
bytecode; following look AspectJ
how in use;
Download and install
AspectJ
official website address: https://www.eclipse.org/aspectj/
Directly download the latest version:AspectJ 1.9.6
; directly run the following command to install:java -jar aspectj-1.9.6.jar
Specify the installation directory, and then configure classPath
and path
:
ASPECTJ_HOME=E:\aspectj1.9
CLASSPATH=...%ASPECTJ_HOME%\lib\aspectjrt.jar
PATH=...%ASPECTJ_HOME%\bin
Compile and use
You can directly useAspectJ
provided byDemo
to test under theexamples\tjp
There are twojava
files, which areDemo.java
andGetInfo.java
.Demo
is our normaljava
file, andGetInfo
is an enhanced file. There are someAspectJ
grammars that need to beajc
command.E:\aspectj1.9\doc\examples\tjp>ajc -argfile files.lst E:\aspectj1.9\doc\examples\tjp>cd .. E:\aspectj1.9\doc\examples>java tjp.Demo Intercepted message: foo in class: tjp.Demo Arguments: 0. i : int = 1 1. o : java.lang.Object = tjp.Demo@6e3c1e69 Running original method: Demo.foo(1, tjp.Demo@6e3c1e69) result: null Intercepted message: bar in class: tjp.Demo Arguments: 0. j : java.lang.Integer = 3 Running original method: Demo.bar(3) result: Demo.bar(3) Demo.bar(3)
It can be found that the new class file compiled by ajc, the two methods of go and bar have been enhanced, log output has been added before and after the method call, and the method parameters; it can be found that AspectJ
has already done the class file before running Enhanced processing; Spring AOP borrows AspectJ
, but does not use AspectJ
in its implementation but uses dynamic enhancement technology;
ASM
ASM
is a general Java
bytecode manipulation and analysis framework, which can be used to modify existing classes or directly generate classes in binary form; ASM
provides some common bytecode conversion and analysis algorithms from which you can build customizations Complex conversion and code analysis tools; several core classes:
- ClassVisitor: for generating and converting compiled classes
ASM API
basedClassVisitor
abstract class, each class corresponding to the methods of the same name as the file structure; - ClassReader: The main function of this type is to read bytecode files, and then notify
ClassVisitor
the read data; - ClassWriter: It inherits from
ClassVisitor
and is mainly used to generate classes;
ASM partial low-level bytecode operation, all need to be familiar with bytecode commands, but high performance; for example, FastJson, Cglib, Lombok, etc. all rely on ASM; the general operation steps are to first load the original Class file, and then pass the visitor mode Access all elements, transform each element in the process of access, and finally regenerate a bytecode binary file, and load a new Class or reload according to requirements;
More references: ASM Introduction
Javassist
Just because ASM
needs to be familiar with bytecode commands, and the bytecode itself is more obscure, so there is an easier to understand enhancement tool Javassist
, which can be directly coded in Java without knowing the relevant bytecode commands. It is more friendly to developers, of course, the performance is definitely not as good as ASM
. Let's take a look at a few common classes:
- ClassPool: It can be simply understood as the pool for storing classes, all
CtClass
must be obtained from the pool; CtClass
pair can be obtained by the fully qualified name of a class;- CtMethod: The method in the corresponding class, the specified method
CtClass
- CtField: Corresponding to the attribute in the class, you can get the specified attribute
CtClass
Combine the above core classes to see a simple log enhancement example:
public class JavassistTest {
public static void main(String[] args) throws Exception {
//增强后的类信息存放路径
CtClass.debugDump = "./dump";
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("com.zh.asm.TestService");
CtMethod m = cc.getDeclaredMethod("query");
m.insertBefore("{ System.out.println(\"start\"); }");
m.insertAfter("{ System.out.println(\"end\"); }");
TestService h = (TestService) c.newInstance();
h.query();
}
}
Dubbo
uses Javassist
to do dynamic compilation processing, JBoss
uses Javassist
to do AOP
processing, etc.;
More: http://www.javassist.org/tutorial/tutorial.html
Cglib
Cglib
is a powerful and high-performance code generation package. The bottom layer depends on ASM
; it provides a good supplement JDK
Java
does not support the situation without interfaces. In addition, Cglib
is more powerful; several cores The classes are as follows:
- Enhancer:
Cglib
of the most commonly used classes inProxy
, which is similar to the 060d3e732820cf class introduced in the dynamic proxy. The difference is thatEnhancer
can not only proxy the ordinaryclass
, but also proxy interfaces; - MethodInterceptor: interceptors, when you call the target method,
CGLib
calls backMethodInterceptor
interface methods to intercept, to realize your own proxy logic, similar toJDK
inInvocationHandler
interfaces;
public class CgLibProxy {
public static void main(String[] args) {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:/asm/cglib");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TestService.class);
enhancer.setCallback(new MyMethodInterceptor());
TestService testService = (TestService)enhancer.create();
testService.query();
}
}
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("增强处理");
Object object = proxy.invokeSuper(obj, args);
return object;
}
}
Cglib will dynamically generate a proxy class. When it is actually executed, it is actually the proxy class. The original class is called in the proxy class to achieve functional enhancements;
Java Proxy
The reflection mechanism is used to create proxy classes at runtime; the interface and the proxy class remain unchanged, and a handler
class is constructed to implement the InvocationHandler
interface; the core classes are as follows:
- Proxy: Specify a
ClassLoader
object and a group ofinterface
to create a dynamic proxy class; - InvocationHandler: Create your own invocation handler, that is, enhance processing;
public class MyHandler implements InvocationHandler{
private Object object;
public MyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke...");
method.invoke(object, args);
System.out.println("After invoke...");
return null;
}
}
Obtained by reflection dynamic proxy class constructor, the dynamic proxy class instance created by the constructor; and Cglib
inside bottom dependence ASM
, stronger than using reflective properties; FastJson
in use is ASM
instead of using reflection, Spring AOP
implementations are Use Cglib
to achieve.
Loading problem
The above is a brief introduction to various bytecode enhancement technologies. Regardless of the enhancement technology, the class information after the enhancement needs to be loaded. According to the different enhancement technologies used, and the role of the enhancement, the class loading used The method is also different, and the following situations are roughly summarized;
Static compilation
This situation is described above AspectJ
technology, before running on to class
do enhancement processing, so there is no difference between loading and loading a normal class, during the run may not know class
file has been enhanced; this This way of class loading is the simplest;
Dynamic proxy
This method uses dynamic enhancement technology to create a proxy class. The proxy class has its own unique name. The proxy class implements the interface class or inherits from the original class. In fact, a new class is generated, which is also mentioned ASM
Two functions: generation class and conversion class; FastJson
is also ASM
in the generation class function of 060d3e73287547; so in this case, only one class loading is required; ASM
does not provide class loading, but several other dynamic enhancement technologies are provided Class loading function;
Hot update
This situation is the most complicated. If the class that needs to be enhanced has been loaded into the memory, how to reload the class after the bytecode is enhanced; instrument
is a class library provided by the JVM that can modify the loaded classes, specifically for Java Instrumentation services written in the language provide support; before JDK 1.6, instrument
can only take effect when the JVM just starts to load classes, but after JDK 1.6, instrument
supports the modification of class definitions at runtime; specific use needs to provide one ClassFileTransformer
implementation class implements the transform method. This method returns a byte array, which can be generated using the bytecode enhancement tool introduced above;
Using Instrumentation
, developers can build an application-independent agent program ( Agent
) to monitor and assist JVM
, and can even replace and modify certain class definitions. With this function, developers can implement more flexible runtime virtual machine monitoring and Java class operations. This feature actually provides a virtual machine-level support for AOP
implementation, so that developers do not need to control JDK
Do any upgrades and changes, you can realize some of the functions of AOP
instrument
introduced above relies on JPDA
: Java platform debugging framework ( Java Platform Debugger Architecture
), which is a set of interfaces specially provided by the Java virtual machine for debugging and monitoring virtual machines; JPDA
composed of three specifications: JVMTI(JVM Tool Interface)
, JDWP(Java Debug Wire Protocol)
, JDI(Java Debug Interface)
;
More: https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/
to sum up
This article briefly introduces some commonly used bytecode enhancement technologies. It is the support of these underlying technologies that help us greatly improve the efficiency of development during the development process. For example, lombok、aop
etc.; improve performance, such as FastJson、ReflectASM
etc.; cooperate with Java Agent
for hot update and many more.
Thanks for attention
You can follow the WeChat public "160d3e7328779d roll back code ", read it as soon as possible, the article is continuously updated; focus on Java source code, architecture, algorithm and interview.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。