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() {
        }
    }

}
上一篇下一篇

猜你喜欢

热点阅读