前言
學(xué)習(xí)某系統(tǒng)時,大哥跟我說正向流程和反向流程都需要了解(當(dāng)然這里是因?yàn)檎蛱y了,涉及到使用asm操作字節(jié)碼猾瘸,正向我做不到啊6啊)牵触。阿里最近開源的jvm-sandbox讓我再一次跪拜。
基本原理
sandbox的基本原理是利用Java的Instrument做jvm級別的AOP咐低。Sandbox將代碼執(zhí)行過程分為如下幾種:
AOP的作用是在這些點(diǎn)植入控制代碼揽思,當(dāng)程序運(yùn)行到植入點(diǎn)時(即事件發(fā)生)见擦,通過調(diào)用事件監(jiān)聽器EventListenerHandlers瞧挤,調(diào)用用戶自定義行為。
Event控制
為了方便控制切入的代碼儡湾,sandbox提供active特恬、frozen等功能,可以方便打開和關(guān)閉對于功能徐钠。簡單點(diǎn)說就是:
1癌刽、用戶自定義事件會分配一個唯一id,即listenerid尝丐。
2显拜、當(dāng)自定義的Module激活時,把它放入全局的globalEventListenerMap中爹袁;凍結(jié)是就移除远荠。
3、AOP植入的代碼里會把listenerid也植入進(jìn)入失息,在Event的處理流程中譬淳,如果沒有找到對應(yīng)的Listener,響應(yīng)功能就不會執(zhí)行盹兢。
模塊加載
sandbox的命令行會轉(zhuǎn)為http請求邻梆,使用內(nèi)置的jetty實(shí)現(xiàn)命令處理。如查看sandbox的信息接口
curl localhost:34023/sandbox/module/http/info/version
模塊處理主要是在ModuleHttpServlet實(shí)現(xiàn)绎秒。
DUMP
由于sandbox的Spy類的package是java開頭的浦妄,所以需要改一下。SpyUtils2把Spy類改為不是java開頭见芹。
package de;
import com.alibaba.jvm.sandbox.api.ProcessControlException;
import com.alibaba.jvm.sandbox.api.event.Event;
import com.alibaba.jvm.sandbox.api.listener.EventListener;
import com.alibaba.jvm.sandbox.core.CoreConfigure;
import com.alibaba.jvm.sandbox.core.enhance.weaver.EventListenerHandlers;
import com.alibaba.jvm.sandbox.core.util.SpyUtils2;
import com.alibaba.jvm.sandbox.spy.Spy;
import java.text.SimpleDateFormat;
import java.util.Date;
public abstract class Clock {
private final SimpleDateFormat clockDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final String formatDate(Date date) {
return this.clockDateFormat.format(date);
}
final Date nowDate() {
return new Date();
}
final String report() {
this.checkState();
return this.formatDate(this.nowDate());
}
abstract void checkState();
abstract void delay() throws InterruptedException;
final void loopReport() throws InterruptedException {
do {
try {
System.out.println(this.report());
}
catch (Throwable throwable) {
throwable.printStackTrace();
}
this.delay();
} while (true);
}
public static void main(String[] arrstring) throws Throwable {
// 初始化coremodule
CoreConfigure.toConfigure("","");
// 時間類型
Event.Type[] eventTypeArray = new Event.Type[1];
eventTypeArray[0] = Event.Type.THROWS;
// 激活listen剂娄,listenerid = 1
EventListenerHandlers.getSingleton()
.active(1, new EventListener() {
@Override
public void onEvent(Event event) throws Throwable {
// 立即返回
ProcessControlException.throwReturnImmediately(null);
}
},
// 指定監(jiān)聽的事件為拋出異常
eventTypeArray );
// 初始化spy類
SpyUtils2.init();
// 調(diào)用clock
new BrokenClock().loopReport();
}
static class BrokenClock extends Clock {
@Override
void checkState() {
try {
Spy.Ret ret = Spy.spyMethodOnBefore((Object[])new Object[0], (int)1, (int)4, (String)"Clock$BrokenClock", (String)"checkState", (String)"()V", (Object)this);
int n = ret.state;
if (n == 1) return;
if (n != 2) {
throw new IllegalStateException();
}
throw (Throwable)ret.respond;
}
catch (Throwable throwable) {
try {
Spy.Ret ret = Spy.spyMethodOnThrows((Throwable) throwable, (int) 1);
int n = ret.state;
if (n == 1) return;
if (n == 2) throw (Throwable) ret.respond;
// throw throwable;
}catch (Throwable tt){
tt.printStackTrace();
}
}
}
@Override
void delay() throws InterruptedException {
Thread.sleep(10000L);
}
BrokenClock() {
}
}
}