当前位置: 首页 > news >正文

阿里开源-JVM-SandBox

阿里开源-JVM-SandBox


阿里开源-JVM-SandBox

  • 阿里开源-JVM-SandBox
    • @[TOC](阿里开源-JVM-SandBox)
  • 一、JVM-SandBox能解决什么问题?
  • 二、使用步骤
    • 1.开源代码
    • 2.使用示例
  • 三、总结

一、JVM-SandBox能解决什么问题?

线上故障定位
线上系统流控
线上故障模拟
方法请求录制和结果回放
动态日志打印
安全信息监测和脱敏
JVM-SANDBOX还能帮助你做很多很多,取决于你的脑洞有多大了。

二、使用步骤

1.开源代码

开源代码库: https://github.com/alibaba/jvm-sandbox

2.使用示例

修复破损的时钟(gitlab 示例):

【准备阶段】
我们定义了一个钟,期望可以实现每隔一定的时间进行报时(gitlab 代码)。

package com.taobao.demo;

/**
 * 报时的钟
 */
public class Clock {

    // 日期格式化
    private final java.text.SimpleDateFormat clockDateFormat
            = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 状态检查
     */
    final void checkState() {
        throw new IllegalStateException("STATE ERROR!");
    }

    /**
     * 获取当前时间
     *
     * @return 当前时间
     */
    final java.util.Date now() {
        return new java.util.Date();
    }

    /**
     * 报告时间
     *
     * @return 报告时间
     */
    final String report() {
        checkState();
        return clockDateFormat.format(now());
    }

    /**
     * 循环播报时间
     */
    final void loopReport() throws InterruptedException {
        while (true) {
            try {
                System.out.println(report());
            } catch (Throwable cause) {
                cause.printStackTrace();
            }
            Thread.sleep(1000);
        }
    }

    public static void main(String... args) throws InterruptedException {
        new Clock().loopReport();
    }

}

运行代码
很明显,这个钟的实现有问题,运行起来没有正确的报时,但却一直在报异常!
问题分析
问题出在了checkState()方法上,这个方法中抛出了异常。接下来我们通过构建一个沙箱模块作为例子,修复这个损坏的钟!

解决方案
如果能直接修改checkState()方法的执行逻辑,让其不再抛异常,而是直接返回,那么一切就迎刃而解。但如何在不修改目标代码、不重启目标应用的情况下实现这个功能呢?
【修复阶段】
创建一个Java工程
1、pom 文件 引入sandbox 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>box-mock</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>box-mock</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.jvm.sandbox</groupId>
            <artifactId>sandbox</artifactId>
            <version>1.3.1</version>
            <type>pom</type>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba.jvm.sandbox/sandbox-api -->
        <dependency>
            <groupId>com.alibaba.jvm.sandbox</groupId>
            <artifactId>sandbox-api</artifactId>
            <version>1.3.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba.jvm.sandbox/sandbox-common-api -->
        <dependency>
            <groupId>com.alibaba.jvm.sandbox</groupId>
            <artifactId>sandbox-common-api</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba.jvm.sandbox/sandbox-core -->
        <dependency>
            <groupId>com.alibaba.jvm.sandbox</groupId>
            <artifactId>sandbox-core</artifactId>
            <version>1.3.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.sun</groupId>
                    <artifactId>tools</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.kohsuke.metainf-services</groupId>
            <artifactId>metainf-services</artifactId>
            <version>1.8</version>
        </dependency>
    </dependencies>

    <build>
        <!--<finalName>test-1.0-SNAPSHOT</finalName>-->
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
<!--                            <mainClass>test.core.Core</mainClass>-->
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <!--下面是为了使用 mvn package命令,如果不加则使用mvn assembly-->
                <executions>
                    <execution>
                        <id>make-assemble</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

2、编写你要实现的代码逻辑

package com.alibaba.jvm.sandbox.demo;

import com.alibaba.jvm.sandbox.api.Information;
import com.alibaba.jvm.sandbox.api.Module;
import com.alibaba.jvm.sandbox.api.ProcessController;
import com.alibaba.jvm.sandbox.api.annotation.Command;
import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import org.kohsuke.MetaInfServices;

import javax.annotation.Resource;

/***
* 方式一 实现 Module
**/
@MetaInfServices(Module.class)
@Information(id = "broken-clock-tinker")
public class BrokenClockTinkerModule implements Module {

    @Resource
    private ModuleEventWatcher moduleEventWatcher;

    @Command("repairCheckState")
    public void repairCheckState() {

        new EventWatchBuilder(moduleEventWatcher)
                .onClass("com.taobao.demo.Clock")
                .onBehavior("checkState")
                .onWatch(new AdviceListener() {

                    /**
                     * 拦截{@code com.taobao.demo.Clock#checkState()}方法,当这个方法抛出异常时将会被
                     * AdviceListener#afterThrowing()所拦截
                     */
                    @Override
                    protected void afterThrowing(Advice advice) throws Throwable {
                        
                        // 在此,你可以通过ProcessController来改变原有方法的执行流程
                        // 这里的代码意义是:改变原方法抛出异常的行为,变更为立即返回;void返回值用null表示
                        ProcessController.returnImmediately(null);
                    }
                });

    }

}
###############分割线#######################

package com.example.boxmock.mock;

import com.alibaba.jvm.sandbox.api.Information;
import com.alibaba.jvm.sandbox.api.LoadCompleted;
import com.alibaba.jvm.sandbox.api.Module;
import com.alibaba.jvm.sandbox.api.ProcessController;
import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import org.kohsuke.MetaInfServices;

import javax.annotation.Resource;

/**
 * 方式二 实现 Module, LoadCompleted
 * Created on 2022-03-13
 */

@MetaInfServices(Module.class)
@Information(id = "broken-clock-tinker")
public class BrokenClockTinkerModule  implements Module, LoadCompleted {
    @Resource
    private ModuleEventWatcher moduleEventWatcher;

    @Override
    public void loadCompleted() {
        new EventWatchBuilder(moduleEventWatcher)
                .onClass("com.taobao.demo.Clock")
                .onBehavior("checkState")
                .onWatch(new AdviceListener() {

                    /**
                     * 拦截{@code com.taobao.demo.Clock#checkState()}方法,当这个方法抛出异常时将会被
                     * AdviceListener#afterThrowing()所拦截
                     */

                    @Override
                    protected void after(Advice advice) throws Throwable {
                        ProcessController.returnImmediately(true);
                    }

                });
    }
}

方式一、方式二区别在于后面启动JVM-sanbox 方式不同

3、修复时钟

3.1、编译部署clock-tinker模块 运行命令完成打包

mvn clean package

3.2、下载并安装最新版本阿里SandBox包:

下载地址:https://ompc.oss.aliyuncs.com/jvm-sandbox/release/sandbox-stable-bin.zip
解压: unzip sandbox-stable-bin.zip

3.3、将修复代码打好的包复制到解压后的 sandbox/sandbox-module/目录下

cp target/****-SNAPSHOT-jar-with-dependencies.jar /sandbox/sandbox-module/

3.4 查看 报错的 Clock 代码的 进程号:

命令: jps 

在这里插入图片描述3.5 启动沙箱
假设目标进程号:64927
启动沙箱 进入sandbox/bin 执行启动脚本

./sandbox.sh -p 64927


              NAMESPACE : default
                VERSION : 1.2.0
                   MODE : ATTACH
            SERVER_ADDR : 0.0.0.0
            SERVER_PORT : 56854
         UNSAFE_SUPPORT : ENABLE
           SANDBOX_HOME : /Users/vlinux/opt/sandbox
      SYSTEM_MODULE_LIB : /Users/vlinux/opt/sandbox/module
        USER_MODULE_LIB : ~/.sandbox-module;
    SYSTEM_PROVIDER_LIB : /Users/vlinux/opt/sandbox/provider
     EVENT_POOL_SUPPORT : DISABLE

查看模块

./sandbox.sh -p 64229 -l


broken-clock-tinker ACTIVE  LOADED  0  0  UNKNOW_VERSION  UNKNOW_AUTHOR
sandbox-info        ACTIVE  LOADED  0  0  0.0.4           luanjia@taobao.com
sandbox-module-mgr  ACTIVE  LOADED  0  0  0.0.2           luanjia@taobao.com
sandbox-control     ACTIVE  LOADED  0  0  0.0.3           luanjia@taobao.com
total=4

可以看到broken-clock-tinker模块已经正确被沙箱所加载

如果修复代码用的是方法二 、到此为止 破损的时钟就已经被修复了,但是如果用的是方法一 修复clock#checkState()方法还需要一个触发操作

./sandbox.sh -p 64229 -d 'broken-clock-tinker/repairCheckState'

除此之外 也可以用接口形式触发 参考:https://www.cnblogs.com/moonpool/p/14510443.html

3.6 问题修复
过一会,模块生效完成,你就会发现原本一直抛异常的钟已经开始在刷新时间了,

java.lang.IllegalStateException: STATE ERROR!
    at com.taobao.demo.Clock.checkState(Clock.java:16)
    at com.taobao.demo.Clock.report(Clock.java:34)
    at com.taobao.demo.Clock.loopReport(Clock.java:44)
    at com.taobao.demo.Clock.main(Clock.java:53)
java.lang.IllegalStateException: STATE ERROR!
    at com.taobao.demo.Clock.checkState(Clock.java:16)
    at com.taobao.demo.Clock.report(Clock.java:34)
    at com.taobao.demo.Clock.loopReport(Clock.java:44)
    at com.taobao.demo.Clock.main(Clock.java:53)
java.lang.IllegalStateException: STATE ERROR!
    at com.taobao.demo.Clock.checkState(Clock.java:16)
    at com.taobao.demo.Clock.report(Clock.java:34)
    at com.taobao.demo.Clock.loopReport(Clock.java:44)
    at com.taobao.demo.Clock.main(Clock.java:53)      
2018-10-23 22:31:39
2018-10-23 22:31:40
2018-10-23 22:31:41
2018-10-23 22:31:42
2018-10-23 22:31:43
2018-10-23 22:31:44

恢复被修复的check()方法
当你卸载掉JVM-SANDBOX时候,你就会发现原本已经被修复好的钟,又开始继续报错了。原因是原来通过clock-tinker模块修复的checkState()方法随着沙箱的卸载又恢复成原来错误的代码流程。

3.7、卸载沙箱

./sandbox.sh -p 64229 -S

三、总结

可以通过这个工具最很多东西比如mock 网上有个很不错的mock开源项目
https://github.com/chufusheng/imock

相关文章:

  • 人工神经网络基本原理概述总结
  • Zemax操作38--POP(物理光学传播)的用法
  • (小白学Java)Java简介和基本配置
  • Cyanine5.5 tetrazine|Cy5.5-tetrazine|花青素Cy5.5四嗪
  • 阿里巴巴、阿里云Java面试题、笔试题(含答案)
  • git常用操作总结
  • 如何用小程序端进行测试?
  • CREO:CREO软件之工程图【布局】之一般视图、投影视图、详细视图、局部剖视图、向视图、局部放大视图、旋转剖视图的简介及其使用方法(图文教程)之详细攻略
  • 【网络通信】websocket如何断线重连
  • T Chat 第九期「 李泽磊 - 我在百度做阅读器 」9 月 1 日晚 8 点开播
  • Git从入门到项目实战,一篇文章吃透Git
  • 1.5-36:计算多项式的值
  • uniapp 学习笔记二十一 路由跳转及产品详情数据渲染
  • 怎么预防鸡葡萄球菌病 防治鸡球菌病的特效药
  • 阿里巴巴中国站1688按关键词搜索商品api电商数据接口
  • ECMAScript6(0):ES6简明参考手册
  • FastReport在线报表设计器工作原理
  • Git同步原始仓库到Fork仓库中
  • js作用域和this的理解
  • oschina
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 深入浅出Node.js
  • 深入浅出webpack学习(1)--核心概念
  • Hibernate主键生成策略及选择
  • Nginx实现动静分离
  • 阿里云ACE认证学习知识点梳理
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (09)Hive——CTE 公共表达式
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (javascript)再说document.body.scrollTop的使用问题
  • (LeetCode 49)Anagrams
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)计算机毕业设计高校学生选课系统
  • (三十五)大数据实战——Superset可视化平台搭建
  • (转)Linq学习笔记
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET 解决重复提交问题
  • .net 生成二级域名
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .NET 事件模型教程(二)
  • .NET和.COM和.CN域名区别
  • .php文件都打不开,打不开php文件怎么办
  • .pop ----remove 删除
  • @Autowired标签与 @Resource标签 的区别
  • @Transactional 详解
  • [ Linux ] Linux信号概述 信号的产生
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [ 转载 ] SharePoint 资料
  • [BZOJ] 2044: 三维导弹拦截
  • [bzoj4010][HNOI2015]菜肴制作_贪心_拓扑排序