字节码编程ASM之生成变量并sout

写在前面

本文看下如何通过asm生成变量并sout。

1:代码

直接看代码吧,注释很详细,有不懂的,留言告诉我:

package com.dahuyuo.asmtest;

import org.objectweb.asm.*;
import org.objectweb.asm.commons.AdviceAdapter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;

import static org.objectweb.asm.Opcodes.ASM5;

public class YY extends ClassLoader {

    public static void main(String[] args) throws Exception {
        ClassReader cr = new ClassReader("com.dahuyuo.asmtest.XX");
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
        cr.accept(new ClassVisitor(ASM5, cw) {
            public MethodVisitor visitMethod(int access, String name, String
                    descriptor, String signature, String[] exceptions) {
                // 方法过滤
                if (!"didi".equals(name)) {
                    return super.visitMethod(access, name, descriptor,
                            signature, exceptions);
                }
                MethodVisitor mv = super.visitMethod(access, name, descriptor,
                        signature, exceptions);
                return new AdviceAdapter(ASM5, mv, access, name, descriptor) {
                    protected void onMethodEnter() {
//                        super.onMethodEnter();
                        // 这里不管定义啥类型都可以用Type.LONG_TYPE,没搞懂是干啥的
                        int intVar1 = newLocal(Type.INT_TYPE); // 创建一个int类型的局部变量 相当于int var;
                        mv.visitLdcInsn(99); // 将常量99加载到操作数栈的栈顶
                        mv.visitVarInsn(ISTORE, intVar1); // 将栈顶值赋值给本地变量 int var = 99;
                        mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // 将静态变量System.out压倒栈顶
                        mv.visitVarInsn(ILOAD, intVar1); // 将整数变量压到栈顶
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false); // 出栈System.out,整数变量,并调用sout(int)完成输出
//

//                        int intVar2 = newLocal(Type.INT_TYPE);
//                        mv.visitTypeInsn(NEW, "java/lang/String"); // new String()然后推到栈顶
//                        mv.visitInsn(DUP); // 复制栈顶元素
                        int nextLocal = this.nextLocal; // 获取当前可用的局部变量表位置??
                        mv.visitLdcInsn("pppp"); // 加载常量到栈顶
                        mv.visitVarInsn(ASTORE, nextLocal); // 将栈顶string对象复制给局部变量
//                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/String", "<init>", "(Ljava/lang/String;)V", false); // 调用构造函数完成string对象创建
//                        mv.visitVarInsn(ASTORE, this.nextLocal);


                        mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); // 将静态变量System.out压倒栈顶
                        mv.visitVarInsn(ALOAD, nextLocal); // 将string变量压到栈顶
                        mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); // 出栈System.out,整数变量,并调用sout(string)完成输出
                    }

                    public void visitMaxs(int maxStack, int maxLocals) {
                        super.visitMaxs(maxStack, maxLocals);
                    }

                    protected void onMethodExit(int opcode) {
                        super.onMethodExit(opcode);
                    }
                };
            }
        }, ClassReader.EXPAND_FRAMES);
        // 获取后的字节码
        byte[] byteAfterInstrument = cw.toByteArray();


        outputClazz(byteAfterInstrument, "xxvv");

        // 测试方法
        Class<?> clazz = new
                YY().defineClass("com.dahuyuo.asmtest.XX", byteAfterInstrument, 0, byteAfterInstrument.length);
        Method didi = clazz.getMethod("didi");
        didi.invoke(clazz.newInstance());


    }

    private static void outputClazz(byte[] bytes, String className) {
        // 输出类字节码
        FileOutputStream out = null;
        try {
            String pathName = YY.class.getResource("/").getPath() + className + "_after_instrument.class";
            out = new FileOutputStream(new File(pathName));
            System.out.println("插桩后代码输出路径:" + pathName);
            out.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != out) try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

用来进行插桩的XX类如下:

public class XX {
  /*  public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println(a + b);
    }*/

    public void didi() {

    }
}

运行测试:
在这里插入图片描述
查看生成的字节码:
在这里插入图片描述
就是我们要的效果。

写在后面

参考文章列表

JVM 虚拟机字节码指令表 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/771296.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024亚太赛(中文赛)数学建模竞赛选题建议+初步分析

提示&#xff1a;DS C君认为的难度&#xff1a;B<C<A&#xff0c;开放度&#xff1a;C<A<B。 综合评价来看 A题适合有较强计算几何和优化能力的团队&#xff0c;难度较高&#xff0c;但适用面较窄。 B题数据处理和分析为主&#xff0c;适合数据科学背景的团队…

miniprogram-to-uniapp-微信小程序转换成uniapp项目

文章目录 参考:miniprogram-to-uniapp使用指南第一步第二步第三步第四步【miniprogram-to-uniapp】转换微信小程序”项目为uni-app项目(新版本工具已经支持各种小程序转换) 参考: 小程序技能树 uni-app基础知识总结 miniprogram-to-uniapp使用指南 第一步 win + R 输入…

网络问题排查问题记录

一、问题描述 1.1 问题产生记录 准生产环境报出如下错误&#xff1a;连接某个服务器的时候出现连接超时现象&#xff1b;服务间调用是通过feignnacos实现的&#xff1b;服务部署是用k8s实现的&#xff1b;初步判断是A->B调用是服务端出了初五 二、问题定位 2.1 问题排查记录…

Maven:下载配置教学(2024版 最简)

文章目录 一、Maven下载1.1 下载官网1.2 下载压缩包1.3 解压1.4 创建repo文件夹 二、Maven配置2.1 环境变量2.1.1 新建系统变量2.1.2 添加Path 2.2 阿里云镜像2.3 JDK2.4 本地仓库2.5 conf文件的全部内容2.6 测试安装配置是否成功 三、IDEA中配置Maven3.1 新配置3.2 推荐配置 四…

实验一 MATLAB \ Python数字图像处理初步

一、实验目的&#xff1a; 1&#xff0e;熟悉及掌握在MATLAB\Python中能够处理哪些格式图像。 2&#xff0e;熟练掌握在MATLAB\Python中如何读取图像。 3&#xff0e;掌握如何利用MATLAB\Python来获取图像的大小、颜色、高度、宽度等等相关信息。 4&#xff0e;掌握如何在M…

阳光倒灌试验太阳辐射系统日光模拟器

太阳光模拟器概述 太阳光模拟器是一种能在实验室环境下模拟太阳光照射特性的设备&#xff0c;广泛应用于材料科学、能源研究、环境科学等领域。通过模拟太阳光的光谱分布和辐射强度&#xff0c;太阳光模拟器可以为科研和工业提供稳定且可重复的光照条件&#xff0c;进而对材料…

c++ primer plus 第15章友,异常和其他:友元类

c primer plus 第15章友&#xff0c;异常和其他&#xff1a;友元类 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;友元类 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的…

iPhone白苹果怎么修复?4个方法解决你的烦恼!

其实iPhone手机出现“白苹果”这事&#xff0c;如果是iPhone轻度用户&#xff0c;可能大家一辈子都不会遇到一次。但如果是iPhone重度用户、越狱爱好者、软件收集狂&#xff0c;可能就会遇到了。 白苹果&#xff0c;一般指iOS设备出现软、硬件故障&#xff0c;卡在一个类似于启…

6年铲屎官测评宠物空气净化器哪款好,热门养宠空气净化器排名

作为一名资深猫奴&#xff0c;发现很多铲屎官每到春秋换季就开始疯狂打喷嚏、突然开始全身过敏。其原因是猫毛一到换季就开始疯狂掉毛&#xff0c;相对于可见猫毛&#xff0c;漂浮在空气中的浮毛就是罪灰祸首。微小的浮毛在空气总容易被人体吸入体内&#xff0c;而浮毛上面附带…

音乐剪辑免费软件有哪些?7个音频剪辑技巧!

音乐剪辑免费软件有很多&#xff0c;但是适合自己或适合剪辑小白的却屈指可数。 音频剪辑软件千千万&#xff0c;如果是没有任何剪辑经验的小白用户&#xff0c;个人建议使用知名度较高的音频剪辑软件。不管是免费还是收费的音频剪辑软件&#xff0c;只要能够解决问题&#xf…

基于opencv的斜光测距及python实现

1.前言 最近做了一个基于opencv的斜光测距的小项目&#xff0c;东西不多&#xff0c;但是很有意思&#xff0c;值得拿出来学一学。项目里面需要比较精确的定位功能&#xff0c;将前人matlab代码移植到python上&#xff0c;并且做了一些优化&#xff0c;简化逻辑(毕竟我是专业的…

如何选择快手矩阵系统:打造高效短视频营销的指南

快手作为中国领先的短视频社交平台&#xff0c;为内容创作者和品牌提供了广阔的展示舞台。为了更高效地管理和扩展在快手上的影响力&#xff0c;快手矩阵系统成为了一个重要的工具。本文将指导您如何选择一个合适的快手矩阵系统&#xff0c;以优化您的内容管理和营销策略。 快…

Kotlin和Java的一些不同点

1.Kotlin 的变量是没有默认值的&#xff08;因此要求初始化&#xff09;&#xff0c;Java的成员变量是有默认值的 Java的成员变量&#xff1a; String name; // 默认值是 null int count; // 默认值是 0不过其实 Java 也只是成员变量有默认值&#xff0c;局部变量也是没有默…

中俄汽车产业链合作前景广阔,东方经济论坛助力双边合作与创新

随着中国汽车零部件企业的竞争力和创新能力不断增强&#xff0c;中国汽车及零部件行业在俄罗斯的市场份额和品牌影响力显著提升&#xff0c;中俄两国在汽车产业链上的合作展现出巨大的潜力和广阔的前景。2024年5月&#xff0c;俄罗斯乘用车新车销量达到12.8万辆&#xff0c;同比…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验15 网络故障导致的路由环路问题

一、实验目的 1.验证因网络故障而导致的静态路由的路由环路问题&#xff1b; 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&#xff0c;完成对应实验。 三、实验内容 1.构建网络拓扑&#xff1b; 2.验证网络故障导致的…

LTSPICE仿真电路:(十九)磁珠的一些简单仿真

1.作用 简单来说就是用来滤波的&#xff0c;将高频信号转化为热量滤除掉&#xff0c;低频有用信号正常通过 2.参数 上图几个参数比较简单&#xff0c;就是字面上的意思&#xff0c;更重要的就是频率阻抗图 不同曲线代表不同型号的磁珠&#xff0c;实际上除了额定电流外&#…

Spring框架的学习SpringMVC(1)

1.什么是MVC (1)MVC其实就是软件架构的一种设计模式&#xff0c;它将软件的系统分为&#xff0c;&#xff08;视图&#xff0c;模型&#xff0c;控制器&#xff09;三个部分 1.1View(视图) 视图也就是&#xff0c;在浏览器显示的那一个部分&#xff0c;是后端数据的呈现 1.…

某DingTalk企典 - Token

⚠️前言⚠️ 本文仅用于学术交流。 学习探讨逆向知识&#xff0c;欢迎私信共享学习心得。 如有侵权&#xff0c;联系博主删除。 请勿商用&#xff0c;否则后果自负。 网址 aHR0cHM6Ly9kaW5ndGFsay5jb20vcWlkaWFuLw 浅聊一下 没毛病&#xff0c;就这字段&#xff0c;有效期…