1.创建一个导出生成类的agent
agent是一个用来个jvm打交道的东西,需要实现一个静态的public static void premain(String agentArgs, Instrumentation inst) 方法.我使用如下的代码创建agent
package ctgu.jagent;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
public class CustomAgent implements ClassFileTransformer {
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(
new CustomAgent());
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer)
throws IllegalClassFormatException {
if (!className.startsWith(
"java") && !className.startsWith(
"sun")) {
int lastIndexOf = className.lastIndexOf(
"/") +
1;
String fileName = className.substring(lastIndexOf) +
".class";
exportClazzToFile(
"E:/javaeeworkspace/bytecode/exported/", fileName, classfileBuffer);
System.out.println(className +
" --> EXPORTED Succeess!");
}
return classfileBuffer;
}
private void exportClazzToFile(String dirPath, String fileName, byte[] data) {
try {
File file =
new File(dirPath + fileName);
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fos =
new FileOutputStream(file);
fos.write(data);
fos.close();
}
catch (Exception e) {
System.out.println(
"exception occured while doing some file operation");
e.printStackTrace();
}
}
}
然后使用eclipse的导出功能导出jar(注意agent必须是jar的形式存在),在向导中使用指定的MANIFEST.MF文件,MANIFEST.MF文件的内容如下
Manifest-Version: 1
.0
Premain-Class:
ctgu.jagent.CustomAgent
注意,这个premain-Class就是带有premain静态方法的类。 如果你使用maven,也可以用如下plugin
<plugin>
<groupId>org.apache.maven.plugins
</groupId>
<artifactId>maven-jar-plugin
</artifactId>
<configuration>
<archive>
<manifestFile>src
/main/resources/META-INF/MANIFEST.MF
</manifestFile>
</archive>
</configuration>
</plugin>
把manifestFile换成你存放自定义MANIFEST.MF的路径,然后mvn package就可以了。
导出的jar包这里假设叫jagent.jar
2. 使用jagent.jar
把jagent.jar放到工程下,运行的时候加上jvm参数
-javaagent:jagent.jar
注意:左右都没有空格,要是jvm提示找不到的话,可以用eclispe把jagent.jar加入到buildpath中。
3.1 使用jdk的代理
private static void javaDynamicProxy() {
HelloService helloService=
new HelloServiceImpl();
MyInvocationHandler handler=
new MyInvocationHandler(helloService);
HelloService proxy = (HelloService)Proxy.newProxyInstance(HelloService.
class.getClassLoader(),
new Class<?>[]{HelloService.
class}, handler);
String sayHello = proxy.sayHello(
"woober");
System.out.println(sayHello);
}
其中MyInvocationHandler的代码如下:
package ctgu.bytecode.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
Object trueTarget;
public MyInvocationHandler(Object target) {
this.trueTarget=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(
"before invoke method:"+method.getName());
Object result = method.invoke(trueTarget, args);
System.out.println(
"invoke finish return:"+result);
return result;
}
}
运行后输出:
ctgu
/bytecode/TestMain --> EXPORTED Succeess!
ctgu
/bytecode/proxy
/service/impl/HelloServiceImpl --> EXPORTED Succeess!
ctgu
/bytecode/proxy
/service/HelloService --> EXPORTED Succeess!
ctgu
/bytecode/proxy/MyInvocationHandler --> EXPORTED Succeess!
com
/sun/proxy/$Proxy0 --> EXPORTED Succeess!
before invoke
method:sayHello
invoke finish
return:Hello woober
Hello woober
在第4部分会分析生成com/sun/proxy/$Proxy0的反编译代码。
3.2 使用cglib代理
private static void cgLibProxy(){
HelloService helloService=
new HelloServiceImpl();
MyMethodIntercepter intercepter=
new MyMethodIntercepter(helloService);
HelloService proxy = (HelloService)Enhancer.create(HelloService.
class,intercepter);
System.err.println(
"Proxy class name is "+proxy.getClass().getName());
System.out.println(proxy.sayHello(
"Woober"));
}
其中MyMethodIntercepter代码如下:
package ctgu.bytecode.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class MyMethodIntercepter implements MethodInterceptor{
Object trueTarget;
public MyMethodIntercepter(Object target) {
trueTarget=target;
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(
"In cglib before invoke");
Object result = proxy.invoke(trueTarget, args);
System.out.println(
"In cglib after invoke");
return result;
}
}
运行输出:
ctgu
/bytecode/TestMain --> EXPORTED Succeess!
net
/sf/cglib
/proxy/Callback --> EXPORTED Succeess!
ctgu
/bytecode/proxy
/service/impl/HelloServiceImpl --> EXPORTED Succeess!
ctgu
/bytecode/proxy
/service/HelloService --> EXPORTED Succeess!
ctgu
/bytecode/proxy/MyMethodIntercepter --> EXPORTED Succeess!
net
/sf/cglib
/proxy/MethodInterceptor --> EXPORTED Succeess!
net
/sf/cglib
/proxy/Enhancer --> EXPORTED Succeess!
中间省略大量cglib的类还有asm的类.....
ctgu
/bytecode/proxy
/service/HelloService$$EnhancerByCGLIB$$
1af19a1d --> EXPORTED Succeess!
net
/sf/cglib
/proxy/MethodProxy --> EXPORTED Succeess!
net
/sf/cglib
/proxy/MethodProxy$CreateInfo --> EXPORTED Succeess!
In cglib before invoke
Proxy class name is ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$
1af19a1d
省略大量cglib的类...
ctgu
/bytecode/proxy
/service/HelloService$$FastClassByCGLIB$$c2826506 --> EXPORTED Succeess!
ctgu
/bytecode/proxy
/service/HelloService$$EnhancerByCGLIB$$
1af19a1d$$FastClassByCGLIB$$a45a31f6 --> EXPORTED Succeess!
In cglib after invoke
Hello Woober
注意这两句话的顺序
In cglib before invoke
Proxy
class name is ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$af19a1d
按理说后面应该在后面这句应该在前面的,因为我使用system.err打的Proxy class name is这一句,跟out不是同一个流,所以以顺序不对(因为err会在eclipse里面标红,比较好看...)
下面重点关注ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$1af19a1d这个类
4. 查看生成类的源码
找一个顺手的反编译器,我用的是Bytecode Viewer ,github地址https://github.com/Konloch/bytecode-viewer
4.1 JDK动态代理反编译
package com.sun.proxy;
import ctgu.bytecode.proxy.service.HelloService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final
class $Proxy0
extends Proxy
implements HelloService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
public final
boolean equals(
Object object) {
try {
return (
Boolean)
this.h.invoke((
Object)
this, m1,
new Object[]{object});
}
catch (
Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var2_2) {
throw new UndeclaredThrowableException(var2_2);
}
}
public final
String sayHello(
String string) {
try {
return (
String)
this.h.invoke((
Object)
this, m3,
new Object[]{
string});
}
catch (
Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var2_2) {
throw new UndeclaredThrowableException(var2_2);
}
}
public final
String toString() {
try {
return (
String)
this.h.invoke((
Object)
this, m2,
null);
}
catch (
Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var1_1) {
throw new UndeclaredThrowableException(var1_1);
}
}
public final int hashCode() {
try {
return (Integer)
this.h.invoke((
Object)
this, m0,
null);
}
catch (
Error | RuntimeException v0) {
throw v0;
}
catch (Throwable var1_1) {
throw new UndeclaredThrowableException(var1_1);
}
}
static {
try {
m1 = Class.forName(
"java.lang.Object").getMethod(
"equals", Class.forName(
"java.lang.Object"));
m3 = Class.forName(
"ctgu.bytecode.proxy.service.HelloService").getMethod(
"sayHello", Class.forName(
"java.lang.String"));
m2 = Class.forName(
"java.lang.Object").getMethod(
"toString",
new Class[
0]);
m0 = Class.forName(
"java.lang.Object").getMethod(
"hashCode",
new Class[
0]);
return;
}
catch (NoSuchMethodException var1) {
throw new NoSuchMethodError(var1.getMessage());
}
catch (ClassNotFoundException var1_1) {
throw new NoClassDefFoundError(var1_1.getMessage());
}
}
}
可以看出来他实现了HelloService接口,实现了sayHello方法,实际调用的时候是使用的invocationHandler并且传入了m3,m3实际就是靠反射拿到的接口中的sayHello方法。
m3 = Class.forName(
"ctgu.bytecode.proxy.service.HelloService").getMethod(
"sayHello", Class.forName(
"java.lang.String"));
4.2 CGLIB动态代理反编译
package ctgu.bytecode.proxy.service;
import java.lang.reflect.*;
import net.sf.cglib.proxy.*;
import net.sf.cglib.core.*;
public class HelloService$
$EnhancerByCGLIB$
$1af19a1d implements HelloService, Factory
{
private boolean CGLIB
$BOUND;
private static final ThreadLocal CGLIB
$THREAD_CALLBACKS;
private static final Callback[] CGLIB
$STATIC_CALLBACKS;
private MethodInterceptor CGLIB
$CALLBACK_0;
private static final Method CGLIB
$finalize$0$Method;
private static final MethodProxy CGLIB
$finalize$0$Proxy;
private static final Object[] CGLIB
$emptyArgs;
private static final Method CGLIB
$equals$1$Method;
private static final MethodProxy CGLIB
$equals$1$Proxy;
private static final Method CGLIB
$toString$2$Method;
private static final MethodProxy CGLIB
$toString$2$Proxy;
private static final Method CGLIB
$hashCode$3$Method;
private static final MethodProxy CGLIB
$hashCode$3$Proxy;
private static final Method CGLIB
$clone$4$Method;
private static final MethodProxy CGLIB
$clone$4$Proxy;
private static final Method CGLIB
$sayHello$5$Method;
private static final MethodProxy CGLIB
$sayHello$5$Proxy;
static void CGLIB
$STATICHOOK1() {
CGLIB
$THREAD_CALLBACKS = new ThreadLocal();
CGLIB
$emptyArgs = new Object[0];
final Class<?>
forName = Class.forName(
"ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$1af19a1d");
final Class<?>
forName2;
final Method[] methods = ReflectUtils.findMethods(new String[] {
"finalize",
"()V",
"equals",
"(Ljava/lang/Object;)Z",
"toString",
"()Ljava/lang/String;",
"hashCode",
"()I",
"clone",
"()Ljava/lang/Object;" }, (
forName2 = Class.forName(
"java.lang.Object")).getDeclaredMethods());
CGLIB
$finalize$0$Method = methods[0];
CGLIB
$finalize$0$Proxy = MethodProxy.create((Class)
forName2, (Class)
forName,
"()V",
"finalize",
"CGLIB$finalize$0");
CGLIB
$equals$1$Method = methods[1];
CGLIB
$equals$1$Proxy = MethodProxy.create((Class)
forName2, (Class)
forName,
"(Ljava/lang/Object;)Z",
"equals",
"CGLIB$equals$1");
CGLIB
$toString$2$Method = methods[2];
CGLIB
$toString$2$Proxy = MethodProxy.create((Class)
forName2, (Class)
forName,
"()Ljava/lang/String;",
"toString",
"CGLIB$toString$2");
CGLIB
$hashCode$3$Method = methods[3];
CGLIB
$hashCode$3$Proxy = MethodProxy.create((Class)
forName2, (Class)
forName,
"()I",
"hashCode",
"CGLIB$hashCode$3");
CGLIB
$clone$4$Method = methods[4];
CGLIB
$clone$4$Proxy = MethodProxy.create((Class)
forName2, (Class)
forName,
"()Ljava/lang/Object;",
"clone",
"CGLIB$clone$4");
final Class<?>
forName3;
CGLIB
$sayHello$5$Method = ReflectUtils.findMethods(new String[] {
"sayHello",
"(Ljava/lang/String;)Ljava/lang/String;" }, (
forName3 = Class.forName(
"ctgu.bytecode.proxy.service.HelloService")).getDeclaredMethods())[0];
CGLIB
$sayHello$5$Proxy = MethodProxy.create((Class)
forName3, (Class)
forName,
"(Ljava/lang/String;)Ljava/lang/String;",
"sayHello",
"CGLIB$sayHello$5");
}
final void CGLIB
$finalize$0() throws Throwable {
super.finalize();
}
protected final void finalize() throws Throwable {
MethodInterceptor cglib
$CALLBACK_2;
MethodInterceptor cglib
$CALLBACK_0;
if ((cglib
$CALLBACK_0 = (cglib
$CALLBACK_2 = this.CGLIB
$CALLBACK_0)) == null) {
CGLIB
$BIND_CALLBACKS(this);
cglib
$CALLBACK_2 = (cglib
$CALLBACK_0 = this.CGLIB
$CALLBACK_0);
}
if (cglib
$CALLBACK_0 != null) {
cglib
$CALLBACK_2.intercept((Object)this, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$finalize$0$Method, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$emptyArgs, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$finalize$0$Proxy);
return;
}
super.finalize();
}
final boolean CGLIB
$equals$1(final Object o) {
return super.equals(o);
}
public final boolean equals(final Object o) {
MethodInterceptor cglib
$CALLBACK_2;
MethodInterceptor cglib
$CALLBACK_0;
if ((cglib
$CALLBACK_0 = (cglib
$CALLBACK_2 = this.CGLIB
$CALLBACK_0)) == null) {
CGLIB
$BIND_CALLBACKS(this);
cglib
$CALLBACK_2 = (cglib
$CALLBACK_0 = this.CGLIB
$CALLBACK_0);
}
if (cglib
$CALLBACK_0 != null) {
final Object intercept = cglib
$CALLBACK_2.intercept((Object)this, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$equals$1$Method, new Object[] { o }, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$equals$1$Proxy);
return intercept != null && (boolean)intercept;
}
return super.equals(o);
}
final String CGLIB
$toString$2() {
return super.toString();
}
public final String
toString() {
MethodInterceptor cglib
$CALLBACK_2;
MethodInterceptor cglib
$CALLBACK_0;
if ((cglib
$CALLBACK_0 = (cglib
$CALLBACK_2 = this.CGLIB
$CALLBACK_0)) == null) {
CGLIB
$BIND_CALLBACKS(this);
cglib
$CALLBACK_2 = (cglib
$CALLBACK_0 = this.CGLIB
$CALLBACK_0);
}
if (cglib
$CALLBACK_0 != null) {
return (String)cglib
$CALLBACK_2.intercept((Object)this, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$toString$2$Method, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$emptyArgs, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$toString$2$Proxy);
}
return super.toString();
}
final int CGLIB
$hashCode$3() {
return super.hashCode();
}
public final int
hashCode() {
MethodInterceptor cglib
$CALLBACK_2;
MethodInterceptor cglib
$CALLBACK_0;
if ((cglib
$CALLBACK_0 = (cglib
$CALLBACK_2 = this.CGLIB
$CALLBACK_0)) == null) {
CGLIB
$BIND_CALLBACKS(this);
cglib
$CALLBACK_2 = (cglib
$CALLBACK_0 = this.CGLIB
$CALLBACK_0);
}
if (cglib
$CALLBACK_0 != null) {
final Object intercept = cglib
$CALLBACK_2.intercept((Object)this, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$hashCode$3$Method, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$emptyArgs, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$hashCode$3$Proxy);
return (intercept == null) ? 0 : ((Number)intercept).intValue();
}
return super.hashCode();
}
final Object CGLIB
$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object
clone() throws CloneNotSupportedException {
MethodInterceptor cglib
$CALLBACK_2;
MethodInterceptor cglib
$CALLBACK_0;
if ((cglib
$CALLBACK_0 = (cglib
$CALLBACK_2 = this.CGLIB
$CALLBACK_0)) == null) {
CGLIB
$BIND_CALLBACKS(this);
cglib
$CALLBACK_2 = (cglib
$CALLBACK_0 = this.CGLIB
$CALLBACK_0);
}
if (cglib
$CALLBACK_0 != null) {
return cglib
$CALLBACK_2.intercept((Object)this, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$clone$4$Method, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$emptyArgs, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$clone$4$Proxy);
}
return super.clone();
}
final String CGLIB
$sayHello$5(final String s) {
return super.sayHello(s);
}
public final String sayHello(final String s) {
MethodInterceptor cglib
$CALLBACK_2;
MethodInterceptor cglib
$CALLBACK_0;
if ((cglib
$CALLBACK_0 = (cglib
$CALLBACK_2 = this.CGLIB
$CALLBACK_0)) == null) {
CGLIB
$BIND_CALLBACKS(this);
cglib
$CALLBACK_2 = (cglib
$CALLBACK_0 = this.CGLIB
$CALLBACK_0);
}
if (cglib
$CALLBACK_0 != null) {
return (String)cglib
$CALLBACK_2.intercept((Object)this, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$sayHello$5$Method, new Object[] { s }, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$sayHello$5$Proxy);
}
return super.sayHello(s);
}
public static MethodProxy CGLIB
$findMethodProxy(final Signature signature) {
final String string = signature.toString();
switch (string.hashCode()) {
case -1816210712: {
if (string.equals(
"sayHello(Ljava/lang/String;)Ljava/lang/String;")) {
return HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$sayHello$5$Proxy;
}
break;
}
case -1574182249: {
if (string.equals(
"finalize()V")) {
return HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$finalize$0$Proxy;
}
break;
}
case -508378822: {
if (string.equals(
"clone()Ljava/lang/Object;")) {
return HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$clone$4$Proxy;
}
break;
}
case 1826985398: {
if (string.equals(
"equals(Ljava/lang/Object;)Z")) {
return HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$equals$1$Proxy;
}
break;
}
case 1913648695: {
if (string.equals(
"toString()Ljava/lang/String;")) {
return HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$toString$2$Proxy;
}
break;
}
case 1984935277: {
if (string.equals(
"hashCode()I")) {
return HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$hashCode$3$Proxy;
}
break;
}
}
return null;
}
public HelloService$
$EnhancerByCGLIB$
$1af19a1d() {
CGLIB
$BIND_CALLBACKS(this);
}
public static void CGLIB
$SET_THREAD_CALLBACKS(final Callback[] array) {
HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$THREAD_CALLBACKS.set(array);
}
public static void CGLIB
$SET_STATIC_CALLBACKS(final Callback[] cglib
$STATIC_CALLBACKS) {
CGLIB
$STATIC_CALLBACKS = cglib
$STATIC_CALLBACKS;
}
private static final void CGLIB
$BIND_CALLBACKS(final Object o) {
final HelloService$
$EnhancerByCGLIB$
$1af19a1d helloService$
$EnhancerByCGLIB$
$1af19a1d = (HelloService$
$EnhancerByCGLIB$
$1af19a1d)o;
if (!helloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$BOUND) {
helloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$BOUND =
true;
Object o2;
if ((o2 = HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$THREAD_CALLBACKS.get()) != null || (o2 = HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$STATIC_CALLBACKS) != null) {
helloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$CALLBACK_0 = (MethodInterceptor)((Callback[])o2)[0];
}
}
}
public Object newInstance(final Callback[] array) {
CGLIB
$SET_THREAD_CALLBACKS(array);
final HelloService$
$EnhancerByCGLIB$
$1af19a1d helloService$
$EnhancerByCGLIB$
$1af19a1d = new HelloService$
$EnhancerByCGLIB$
$1af19a1d();
CGLIB
$SET_THREAD_CALLBACKS(null);
return helloService$
$EnhancerByCGLIB$
$1af19a1d;
}
public Object newInstance(final Callback callback) {
CGLIB
$SET_THREAD_CALLBACKS(new Callback[] { callback });
final HelloService$
$EnhancerByCGLIB$
$1af19a1d helloService$
$EnhancerByCGLIB$
$1af19a1d = new HelloService$
$EnhancerByCGLIB$
$1af19a1d();
CGLIB
$SET_THREAD_CALLBACKS(null);
return helloService$
$EnhancerByCGLIB$
$1af19a1d;
}
public Object newInstance(final Class[] array, final Object[] array2, final Callback[] array3) {
CGLIB
$SET_THREAD_CALLBACKS(array3);
switch (array.length) {
case 0: {
final HelloService$
$EnhancerByCGLIB$
$1af19a1d helloService$
$EnhancerByCGLIB$
$1af19a1d = new HelloService$
$EnhancerByCGLIB$
$1af19a1d();
CGLIB
$SET_THREAD_CALLBACKS(null);
return helloService$
$EnhancerByCGLIB$
$1af19a1d;
}
default: {
throw new IllegalArgumentException(
"Constructor not found");
}
}
}
public Callback getCallback(final int n) {
CGLIB
$BIND_CALLBACKS(this);
Object cglib
$CALLBACK_0 = null;
switch (n) {
case 0: {
cglib
$CALLBACK_0 = this.CGLIB
$CALLBACK_0;
break;
}
default: {
cglib
$CALLBACK_0 = null;
break;
}
}
return (Callback)cglib
$CALLBACK_0;
}
public void
setCallback(final int n, final Callback callback) {
switch (n) {
case 0: {
this.CGLIB
$CALLBACK_0 = (MethodInterceptor)callback;
break;
}
}
}
public Callback[]
getCallbacks() {
CGLIB
$BIND_CALLBACKS(this);
return new Callback[] { this.CGLIB
$CALLBACK_0 };
}
public void
setCallbacks(final Callback[] array) {
this.CGLIB
$CALLBACK_0 = (MethodInterceptor)array[0];
}
static {
CGLIB
$STATICHOOK1();
}
}
生成的类同样实现了 HelloService接口并且实现了Factory接口,Factory接口如下:
public interface Factory {
Object newInstance(Callback callback);
Object newInstance(Callback[] callbacks);
Object newInstance(Class[] types, Object[] args, Callback[] callbacks);
Callback getCallback(int index);
void setCallback(int index, Callback callback);
void setCallbacks(Callback[] callbacks);
Callback[] getCallbacks();
}
直接看生成的sayHello实现
public final String sayHello(
final String s) {
MethodInterceptor cglib$CALLBACK_2;
MethodInterceptor cglib$CALLBACK_0;
if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) ==
null) {
CGLIB$BIND_CALLBACKS(this);
cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);
}
if (cglib$CALLBACK_0 !=
null) {
return (String)cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$
1af19a1d.CGLIB$sayHello$
5$Method,
new Object[] { s }, HelloService$$EnhancerByCGLIB$$
1af19a1d.CGLIB$sayHello$
5$Proxy);
}
return super.sayHello(s);
}
可以看到cglib$CALLBACK_0是通过CGLIB$BIND_CALLBACKS(this)完成的,glib$CALLBACK_2跟glib$CALLBACK_2是一个东西。
再看CGLIB$BIND_CALLBACKS(this)做了啥
private static final void CGLIB
$BIND_CALLBACKS(final Object o) {
final HelloService$
$EnhancerByCGLIB$
$1af19a1d helloService$
$EnhancerByCGLIB$
$1af19a1d = (HelloService$
$EnhancerByCGLIB$
$1af19a1d)o;
if (!helloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$BOUND) {
helloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$BOUND =
true;
Object o2;
if ((o2 = HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$THREAD_CALLBACKS.get()) != null || (o2 = HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$STATIC_CALLBACKS) != null) {
helloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$CALLBACK_0 = (MethodInterceptor)((Callback[])o2)[0];
}
}
}
CGLIB$CALLBACK_0是CGLIB$THREAD_CALLBACKS.get()或者CGLIB$STATIC_CALLBACKS, CGLIB$THREAD_CALLBACKS是一个threadlocal的成员变量。
CGLIB$THREAD_CALLBACKS是由下面的CGLIB$SET_THREAD_CALLBACKS方法来设置的,
public static void CGLIB$SET_THREAD_CALLBACKS(
final Callback[]
array) {
HelloService$$EnhancerByCGLIB$$
1af19a1d.CGLIB$THREAD_CALLBACKS.set(
array);
}
这个方法被Factory接口的newInstance调用
public Object newInstance(
final Callback[]
array) {
CGLIB$SET_THREAD_CALLBACKS(
array);
final HelloService$$EnhancerByCGLIB$$
1af19a1d helloService$$EnhancerByCGLIB$$
1af19a1d =
new HelloService$$EnhancerByCGLIB$$
1af19a1d();
CGLIB$SET_THREAD_CALLBACKS(
null);
return helloService$$EnhancerByCGLIB$$
1af19a1d;
}
public Object newInstance(
final Callback callback) {
CGLIB$SET_THREAD_CALLBACKS(
new Callback[] { callback });
final HelloService$$EnhancerByCGLIB$$
1af19a1d helloService$$EnhancerByCGLIB$$
1af19a1d =
new HelloService$$EnhancerByCGLIB$$
1af19a1d();
CGLIB$SET_THREAD_CALLBACKS(
null);
return helloService$$EnhancerByCGLIB$$
1af19a1d;
}
我看不懂的就是他为什么 CGLIB$SET_THREAD_CALLBACKS(array); 之后又 CGLIB$SET_THREAD_CALLBACKS(null); ???反编译的问题?
对于CGLIB$STATIC_CALLBACKS是由
public
static void CGLIB$SET_STATIC_
CALLBACKS(final Callback[] cglib$STATIC_
CALLBACKS) {
CGLIB$STATIC_
CALLBACKS = cglib$STATIC_
CALLBACKS;
}
这个方法赋值上的,但是我没找到调用的地方。
最后看实际上执行的方法的地方,就是掉的intercepter的intercept方法。
(String)cglib
$CALLBACK_2.intercept((Object)this, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$sayHello$5$Method, new Object[] { s }, HelloService$
$EnhancerByCGLIB$
$1af19a1d.CGLIB
$sayHello$5$Proxy);
最后一个参数是个MethodProxy
CGLIB
$sayHello$5$Proxy = MethodProxy.create((Class)
forName3, (Class)
forName,
"(Ljava/lang/String;)Ljava/lang/String;",
"sayHello",
"CGLIB$sayHello$5");
我猜应该是对方法生成了一个代理
final String CGLIB$sayHello$
5(
final String s) {
return super.sayHello(s);
}
关于这个cglib生成的字节码好多反编译工具都不能解析。不保证上面生成代码的正确性
以上转自:http://www.cnblogs.com/ctgulong/p/5011614.html
主要大家看看反编译的动态代理代码,知道动态代理的本质(java反射)