jvm-sandbox反向学习
2018-02-02 本文已影响0人
huiwq1990
前言
学习某系统时,大哥跟我说正向流程和反向流程都需要了解(当然这里是因为正向太难了,涉及到使用asm操作字节码,正向我做不到啊!)。阿里最近开源的jvm-sandbox让我再一次跪拜。
基本原理
sandbox的基本原理是利用Java的Instrument做jvm级别的AOP。Sandbox将代码执行过程分为如下几种:
image.png
AOP的作用是在这些点植入控制代码,当程序运行到植入点时(即事件发生),通过调用事件监听器EventListenerHandlers,调用用户自定义行为。
Event控制
为了方便控制切入的代码,sandbox提供active、frozen等功能,可以方便打开和关闭对于功能。简单点说就是:
1、用户自定义事件会分配一个唯一id,即listenerid。
2、当自定义的Module激活时,把它放入全局的globalEventListenerMap中;冻结是就移除。
3、AOP植入的代码里会把listenerid也植入进入,在Event的处理流程中,如果没有找到对应的Listener,响应功能就不会执行。
模块加载
sandbox的命令行会转为http请求,使用内置的jetty实现命令处理。如查看sandbox的信息接口
curl localhost:34023/sandbox/module/http/info/version
模块处理主要是在ModuleHttpServlet实现。
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);
}
},
// 指定监听的事件为抛出异常
eventTypeArray );
// 初始化spy类
SpyUtils2.init();
// 调用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() {
}
}
}