jvm-sandbox入门, Module编写以及调试笔记

4,515 阅读2分钟

TLDR;

网上介绍jvm-sandbox 的文档大多是从github官方repo粘贴而来, 很多都是粘贴党,但很少有告诉你这个东西究竟如何调试, 如何应用到实际环境中去的。本文会简单谈谈jvm-box的缘来以及就如何编写jvm-sandbox 的module以及如何对编写的module进行调试, 进行一个详细的介绍.

jvm-sandbox 简介

JVM沙箱容器,一种JVM的非侵入式运行期AOP解决方案

下面文档为官方的一些重要文档

jvm-sandbox 官方文档地址

jvm-sandbox 官方REPO及文档地址

jvm-sandbox 架构图

jvm-sandbox 架构

实现关键技术

关键技术简介
JavaAgent可以动态或者静态的把现有代码作用于正在运行的JVM进程
JVMTI强大的Jvm操作工具, 通过对 JVMTI的应用来实现JVM的控制与操作
类加载机制沙箱通过自定义的SandboxClassLoader破坏了双亲委派的约定,实现了和目标应用的类隔离
字节码编织JVM-SANDBOX属于基于Instrumentation的动态编织类的AOP框架,通过精心构造了字节码增强逻辑,使得沙箱的模块能在不违反JDK约束情况下实现对目标应用方法的无侵入运行时AOP拦截

jvm-sandbox的一些主要流程

sandbox agent 执行流程

image.png

sandbox servlet 处理流程

image.png

sandbox 核心处理流程

image.png

jvm-sandbox 第一个 demo

parent 设置为 sandbox的module starter, 主要帮忙解决打包依赖等问题

<parent>
    <groupId>com.alibaba.jvm.sandbox</groupId>
    <artifactId>sandbox-module-starter</artifactId>
    <version>1.3.3</version>
</parent>

示例Module代码

import org.kohsuke.MetaInfServices;
import javax.annotation.Resource;
import java.io.PrintWriter;
import java.util.Map;

/**
 * @author winjeg@qq.com
 */
@MetaInfServices(Module.class)
@Information(id = "test-module", version = "0.0.1", author = "luanjia@taobao.com")
public class TestModule implements Module, ModuleLifecycle {

    @Resource
    private ModuleEventWatcher moduleEventWatcher;

    @Resource
    private ModuleManager moduleManager;

    // ...  此处省略 1000行...

    @Command("demo")
    public void demoMethod(final Map<String, String> param, final PrintWriter writer) {
        if (param != null && param.size() > 0) {
            for (Map.Entry<String, String> entry : param.entrySet()) {
                System.out.printf("key:%s, value:%s", entry.getKey(), entry.getValue());
            }
        }
        String clz = param.get("clz");
        String method = param.get("method");
        final String result = param.get("result");
        new EventWatchBuilder(moduleEventWatcher)
                .onClass(clz)
                .onBehavior(method)
                .onWatch(new AdviceListener() {
                    @Override
                    protected void before(Advice advice) throws Throwable {
                        ProcessController.returnImmediately(result);
                    }
                });
    }
}

jvm sandbox 部署结构

├── bin
│   └── sandbox.sh
├── cfg
│   ├── sandbox-logback.xml
│   ├── sandbox.properties
│   └── version
├── example
│   └── sandbox-debug-module.jar
├── install-local.sh
├── lib
│   ├── sandbox-agent.jar
│   ├── sandbox-core.jar
│   └── sandbox-spy.jar
├── module
│   ├── demo.jar
│   └── sandbox-mgr-module.jar
├── provider
│   └── sandbox-mgr-provider.jar
└── sandbox-module

启动方法1

使用JVM SANDBOX自带的启动脚本,

./sandbox.sh -p {java_process_id}

启动方法2

使用ide进行启动, 启动类为:

com.alibaba.jvm.sandbox.core.CoreLauncher#main

示例启动参数:

{java_process_id} D:/sandbox/lib/sandbox-agent.jar home=D:/sandbox;server.ip=127.0.0.1;server.port=17789;namespace=test_sand

jvm-sandbox 模块调试

进行 JVM sandbox module调试步骤如下:

  1. 正在运行的java进程需要添加远程调试功能

    注: 正在运行的java进程必须要用 run的方式进行,而不是用debug的方式进行

    -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5008
    
  2. 备好了module, 并且打包好,放到指定位置
  3. sandbox.sh 或者 CoreLauncher 把sandbox的agent 附着在 正在运行的 java 应用进程上
  4. 打开 IDE, 设置远程调试为对应地址
  5. 启动远程调试,正常打断点即可调试module.

或许有其他暂未发现的方法, 但上面的方法亲测切实可行, 有任何问题欢迎 邮件我