《arthas源码分析》字节码增强(三)

前言

当执行reset、shutdown命令之后,需要对增强后的目标类进行恢复,

本篇主要对重置命令的实现进行分析。

注意:reset命令对redefine的类无效。redefine后的原来的类不能恢复。如果想重置,需要redefine原始的字节码。 原因是redefine和retransform是不同的机制,详情参见我之前写的文章。

源码分析

ResetCommand#process
@Override
public void process(CommandProcess process) {
    //Instrumentation
    Instrumentation inst = process.session().getInstrumentation();
    //类匹配器
    Matcher matcher = SearchUtils.classNameMatcher(classPattern, isRegEx);
    //增强影响
    EnhancerAffect enhancerAffect = null;
    try {
        enhancerAffect = Enhancer.reset(inst, matcher);
        //响应影响
        process.write(enhancerAffect.toString()).write("\n");
    } catch (UnmodifiableClassException e) {
        // ignore
    } finally {
        //结束命令
        process.end();
    }
}
Enhancer#reset

重置增强类

注意:
当前方法中的transform()返回null,reset只是恢复原字节码内容,无需定义任何增强逻辑。

public static synchronized EnhancerAffect reset(
        final Instrumentation inst,
        final Matcher classNameMatcher) throws UnmodifiableClassException {

    //增强影响
    final EnhancerAffect affect = new EnhancerAffect();
    //被增强的类的集合
    final Set<Class<?>> enhanceClassSet = new HashSet<Class<?>>();

    //从已增强类的缓存中查找要reset的类
    for (Class<?> classInCache : classBytesCache.keySet()) {
        //匹配目标类
        if (classNameMatcher.matching(classInCache.getName())) {
            enhanceClassSet.add(classInCache);
        }
    }

    //定义字节码转换器
    final ClassFileTransformer resetClassFileTransformer = new ClassFileTransformer() {
        @Override
        public byte[] transform(
                ClassLoader loader,
                String className,
                Class<?> classBeingRedefined,
                ProtectionDomain protectionDomain,
                byte[] classfileBuffer) throws IllegalClassFormatException {
            return null;
        }
    };

    try {
        //批量增强
        enhance(inst, resetClassFileTransformer, enhanceClassSet);
        logger.info("Success to reset classes: " + enhanceClassSet);
    } finally {
        //因为已经目标类已经重置,将其从缓存中移除。
        for (Class<?> resetClass : enhanceClassSet) {
            classBytesCache.remove(resetClass);
            affect.cCnt(1);
        }
    }

    return affect;
}
Enhancer#enhance

批量重置。

public static void enhance(Instrumentation inst, ClassFileTransformer transformer, Set<Class<?>> classes)
        throws UnmodifiableClassException {
    try {
        //添加.class文件转换器
        inst.addTransformer(transformer, true);
        int size = classes.size();
        Class<?>[] classArray = new Class<?>[size];
        //复制字节码到classArray
        arraycopy(classes.toArray(), 0, classArray, 0, size);
        if (classArray.length > 0) {
            inst.retransformClasses(classArray);
        }
    } finally {
        //增强完毕,移除transformer
        inst.removeTransformer(transformer);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java Agent是Arthas使用的技术,是Skywalking使用的技术,是一份十分重要的技术。 课程的稀缺性在此之前,市面上并没有针对Java Agent进行系统介绍的课程。 通过搜索引擎查找,会发现与Java Agent相关的内容大多是个人知识总结分享的内容。这些内容有如下特点:内容质量不一详略程度不一学习难度千差万别总体上来说,学习者很难有一个整体认知、系统学习的过程。 课程的设计目标 在构思课程内容时,本课程带有以下目标:课程学习梯度:从简单到复杂,让学习者有一个循序渐进的理解过程。构造完整、统一的知识体系:不是零散的知识点堆砌,而是有一个统一的贯穿始终的知识框架。具有可操作性的代码示例,不只是讲概念,更注意于实践。课程内容安排 本课程通过四章内容对Java Agent相关知识进行讲解:第一章,介绍Agent Jar的个组成部分:Manifest、Agent Class和ClassFileTransformer。第二章,介绍Agent Jar的两种启动方式:从命令行启动和使用Attach机制启动。第章,介绍如何利用Instrumentation API来实现Agent Jar的功能。第四章,Java Agent的应用与技巧。 通过本课程的学习,让同学们更好地建立起一个完整的知识体系:  讲师介绍我叫刘森,南京师范大学研究生毕业,2015年获得信息系统项目管理师(高级),2014年获得系统集成项目管理工程师(中级)。 目前,我的课程都是围绕着“Java字节码”技术展开: 《Java Agent基础篇》是在一个运行JVM当中提供修改字节码的机会《Java ASM系列》(免费课程)是一个操作字节码的类库《Java 8 ClassFile》专注于字节码的理论知识,入选为“51CTO数字化人才证书项目认证课程” 因此,我对字节码技术有较为深入的研究和理解,大家想学习字节码的技术可以找我:字节码技术找刘森,轻松学习又省心~~~ 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值