ASM Java字节码操作框架入门学习 输出Hello World

ASM Java字节码操作框架入门学习 输出Hello World

1.类信息

package org.example;public class Hello {public void say(){System.out.println("hello world");}}

查看字节码信息

image-20230709204204625

 			//动态设置栈大小ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);//设置类的基本信息classWriter.visit(V1_8, //设置JDK版本,ACC_PUBLIC, // 设置权限修饰符,"Hello", //新类的权限定类名,null,//泛型"java/lang/Object", // 父类null//实现的接口);

2.无参构造方法

image-20230709204353627

0 aload_0
1 invokespecial #1 <java/lang/Object.<init> : ()V>
4 return
  			MethodVisitor constructor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);constructor.visitVarInsn(Opcodes.ALOAD, 0); //操作局部变量表 局部变量表第一个存放thisconstructor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);constructor.visitInsn(Opcodes.RETURN); // 调用  return 指令constructor.visitMaxs(1, 1);//方法的最大栈大小  方法的最大局部变量数constructor.visitEnd(); //方法结束

3.say 方法

image-20230709204937753

0 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>
3 ldc #3 <hello world>
5 invokevirtual #4 <java/io/PrintStream.println : (Ljava/lang/String;)V>
8 return
			//添加say方法MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC,//方法修饰符号"say",//方法名"()V",//方法的描述符,用于描述方法的参数类型和返回值类型null,//方法泛型null//可能抛出的异常);//获取System.outmethodVisitor.visitFieldInsn(Opcodes.GETSTATIC,//字段的类型"java/lang/System",//字段所属类的全限定类名"out",//指定字段"Ljava/io/PrintStream;"//字段描述信息);//加载常量methodVisitor.visitLdcInsn("hello world");methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,//方法调用的操作码   "java/io/PrintStream",//方法的权限定类名"println",//方法名"(Ljava/lang/String;)V", //方法修饰符false);//方法调用者是否是接口methodVisitor.visitInsn(Opcodes.RETURN);methodVisitor.visitMaxs(2, 0);methodVisitor.visitEnd();

4.完成类的定义并创建实例调用目标方法

  			// 完成类的定义classWriter.visitEnd();// 将生成的字节码写入文件或加载到内存中byte[] bytecode = classWriter.toByteArray();ClassLoader classLoader = new ClassLoader() {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {return defineClass(name, bytecode, 0, bytecode.length);}};// 加载并实例化Hello类Class<?> helloClass = classLoader.loadClass("Hello");Object helloObject = helloClass.getDeclaredConstructor().newInstance();// 调用say方法helloClass.getMethod("say").invoke(helloObject);

5.相关JVM指令

方法调用

  1. invokestatic:用于调用静态方法。该指令会根据方法的类名、方法名和方法描述符进行方法查找和调用。
  2. invokespecial:用于调用私有方法、构造方法和父类方法。该指令会根据方法的类名、方法名和方法描述符进行方法查找和调用。
  3. invokevirtual:用于调用实例方法。该指令会根据对象的类型和方法的签名进行方法查找和调用。
  4. invokeinterface:用于调用接口方法。该指令会根据接口的类型和方法的签名进行方法查找和调用。
  5. invokedynamic:用于调用动态方法。该指令会通过调用动态绑定方法来实现方法的调用

加载常量或数字

  1. ldc:将常量(包括字符串、整数、浮点数等)加载到操作数栈上。
  2. ldc_w:与ldc类似,但用于加载较大的常量(超过65535个字节)。
  3. bipush:将一个字节大小的整数常量(-128到127之间)加载到操作数栈上。
  4. sipush:将一个短整型常量(-32768到32767之间)加载到操作数栈上。
  5. iconst_:将整数常量(-1到5之间)加载到操作数栈上,其中为0到5之间的数字。 _
  6. fconst:将浮点数常量(0.0、1.0和2.0)加载到操作数栈上,其中为0到2之间的数字。
  7. dconst_:将双精度浮点数常量(0.0和1.0)加载到操作数栈上,其中为0或1。 _
  8. _ lconst_:将长整型常量(0和1)加载到操作数栈上,其中为0或1

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在vscode中配置git bash终端

将以下配置添加到vscode中的settings.json中 "terminal.integrated.profiles.windows": {"PowerShell": {"source": "PowerShell","icon": "terminal-powershell"},"Command Prompt": {"path"…

Vue3+Vite 项目配置 vue-router,并完成路由模块化

前言 我的技术栈&#xff1a;Vue3 Vite TypeScirpt我的包管理工具&#xff1a;pnpm&#xff08;v8.6.6&#xff09;我的 node.js 版本&#xff1a;v16.14.0 一、安装vue-router pnpm install vue-router二、创建页面 在 /src/views 文件夹下创建 home、login、test文件夹…

【数据挖掘从入门到实战】——专栏导读

目录 1、专栏大纲 &#x1f40b;基础部分 &#x1f40b;实战部分 &#x1f40b;竞赛部分 2、代码附录 数据挖掘专栏&#xff0c;包含基本的数据挖掘算法分析和实战&#xff0c;数据挖掘竞赛干货分享等。数据挖掘是从大规模数据集中发现隐藏模式、关联和知识的过程。它结合…

绝了!阿里大佬的“Redis深度核心笔记“,从基础到源码,全是精华

Redis怎么学习&#xff1f; 我晕了&#xff0c;竟然没人好好回答怎么学习Redis&#xff0c;全都是介绍redis的长文。。。这还让人怎么学。我来分享下我自学Reids看过的资料吧 为什么要学习Redis&#xff1f; Redis 是互联网技术架构在存储系统中使用得最为广泛的中间件&…

【环境配置】Conda报错 requests.exceptions.HTTPError

问题&#xff1a; conda 创建新的虚拟环境时报错 Collecting package metadata (current_repodata.json): done Solving environment: done# >>>>>>>>>>>>>>>>>>>>>> ERROR REPORT <<<<<<…

Installation request for phpoffice/phpspreadsheet

办法 composer update --ignore-platform-reqs

SwiftUI的优缺点

2019年WWDC大会上&#xff0c;苹果在压轴环节向大众宣布了基于Swift语言构建的全新UI框架——SwiftUI&#xff0c;开发者可通过它快速为所有的Apple平台创建美观、动态的应用程序。推荐大量使用struct代替类。 SwiftUI 就是⼀种声明式的构建界面的用户接口工具包。 SwiftUI使用…

会话机制【Cookie 和 Session】,登陆页面的模拟实现

前言 小亭子正在努力的学习编程&#xff0c;接下来将开启JavaEE的学习~~ 分享的文章都是学习的笔记和感悟&#xff0c;如有不妥之处希望大佬们批评指正~~ 同时如果本文对你有帮助的话&#xff0c;烦请点赞关注支持一波, 感激不尽~~ 目录 前言 Cookie 和 Session 是什么 Cookie…

Android Binder进程间通讯原理分析

Binder IPC原理 Android系统是基于Linux内核开发的。Linux开发提供了丰富的进程间通讯机制&#xff0c;例如管道、信号、消息队列、共享内存、插口&#xff08;Socket&#xff09; 。而Binder是一套新的通讯工具。 Binder通信采用了c/s架构&#xff0c;所以我们包含了 Client&…

LwIP系列(5):TCP 3次握手+4次挥手+状态机转换

前言 TCP的3次握手、4次挥手以及TCP状态机&#xff0c;是TCP的核心概念&#xff0c;我们在分析LwIp中TCP相关代码流程&#xff0c;也需要熟悉这些流程&#xff0c;本文就详细介绍这些概念。 TCP 3次握手、应用数据交互、4次挥手完整流程 TCP 为什么是3次握手&#xff0c;而不…

【设计模式】第十九章:访问者模式详解及应用案例

系列文章 【设计模式】七大设计原则 【设计模式】第一章&#xff1a;单例模式 【设计模式】第二章&#xff1a;工厂模式 【设计模式】第三章&#xff1a;建造者模式 【设计模式】第四章&#xff1a;原型模式 【设计模式】第五章&#xff1a;适配器模式 【设计模式】第六章&…

删除有序链表中的重复元素II——牛客24

题目描述 法一&#xff09;直接删除法 class Solution{ public:ListNode* deleteDuplicates(ListNode* head) {if(headNULL) return NULL;ListNode* dummy new ListNode(0);dummy->next head;ListNode* cur dummy;while(cur->next!NULL && cur->next->n…