从利用Arthas排查线上Fastjson问题到Java动态字节码技术(下)
上一篇从Arthas的源码引出了Java动态字节码技术,那么这一篇就从几种Java字节码技术出发,看看Arthas是如何通过动态字节码技术做到无侵入的源码增强;
Java大部分情况下都是解释执行的,也就是解释.class
文件,所以如果我们想对原代码进行增强的话,直接接的手段便是从源文件.java
入手,使用静态代理、动态代理、装饰器等设计模式进行功能增强。但很多时候我们作为第三方,没有机会、不方便拿到源码时,这条路就走不通了;此时如果还是想继续其进行功能增强的话,那么只剩一条路了,就是直接对.class
文件下手。
但对于二进制的.class
文件,还有多少人能分清魔数、标识符、各种区域表示的内容呢?所以直接操作字节码也似乎不太现实,那有没有什么抓手呢?
ASM
ASM 是 assembly 汇编 的简称,所以它更偏底层、更贴近底层字节码,所以也就更难使用、更晦涩。
整体思路上是通过Reader将.class
文件读取后,通过一系列API来增强源码,之后通过Writer生成新的.class
文件。
个人不太建议使用这种方式,学习和使用成本都比较高,不直观,太晦涩。
Javaassist
相比于ASM,理解起来不要太简单,不需要了解底层虚拟机指令和晦涩的API,只需要掌握四个核心类即可 ClassPool、CtClass、CtMethod、CtField:
CtClass(compile-time class):编译时 - 类对象,Java中万物皆对象,CtClass是Class在编译时的对象,可以通过类的全限定名来获取到这个CtClass;
与编译时(compile)类对象相似的,我们平时用反射获取到的是运行时(Runtime)类对象;
ClassPool:可以把它简单的理解为一个HashMap,类的全限定名作为key,可以从中获取到CtClass
CtMethod & CtField:类中的方法和属性
利用以上四个类,可以快速实现对源码的增强,比如当你想实现AOP,在原方法执行前和执行后添加功能的时候,只需要先通过ClassPool获取到CtClass,再获取到CtMethod后,就可以调用该方法的insertBefore
和insertAfter
,插入具体代码块了。
Instrument
Instrument是JVM提供的一个对已加载的类进行修改的接口(Interface),打开java.lang.Instrumentation
可以看到清晰的说明。
首先Instrument
是基于 Java Agent
技术的,也就是上一篇中提到的,用 agentmain
和 premain
attache java进程生成的 agent,也就是为 Instrument 在运行的进程中开了一个后门。
在instrument
接口中最重要的方法是 通过ClassFileTransformer
对原class进行 retransform
;
在ClassFileTransformer
中实现想要对原class的增强,该接口只有一个需要被子类实现的方法,就是transform
方法:
package java.lang.instrument;public interface ClassFileTransformer {byte[]transform( ClassLoader loader,String className,Class<?> classBeingRedefined,ProtectionDomain protectionDomain,byte[] classfileBuffer)throws IllegalClassFormatException;
}
举一个直观的例子,福报厂的ttl threadpool
:
package com.alibaba.ttl.threadpool.agent;public class TtlTransformer implements ClassFileTransformer {//类似于责任链,可以添加一系列的 ClassFileTransformer//值得注意的是,这里使用到了Javassistprivate final List<JavassistTransformlet> transformletList = new ArrayList<JavassistTransformlet>();TtlTransformer(List<? extends JavassistTransformlet> transformletList) {for (JavassistTransformlet transformlet : transformletList) {this.transformletList.add(transformlet);logger.info("[TtlTransformer] add Transformlet " + transformlet.getClass() + " success");}}@Overridepublic final byte[] transform(@Nullable final ClassLoader loader, @Nullable final String classFile, final Class<?> classBeingRedefined,final ProtectionDomain protectionDomain, @NonNull final byte[] classFileBuffer) {final String className = toClassName(classFile);//通过classloader和classname加载了原class对象ClassInfo classInfo = new ClassInfo(className, classFileBuffer, loader);//对原class对象,依次应用 ClassFileTransformer,并返回transform后的新class对象for (JavassistTransformlet transformlet : transformletList) {transformlet.doTransform(classInfo);if (classInfo.isModified()) return classInfo.getCtClass().toBytecode();}}
}
这时就可以回到上一篇中Arthas的核心启动类ArthasBootstrap
==> transformerManager = new TransformerManager(instrumentation);
在TransformerManager中,有三类增强功能:watcher/tarce/其余的归为reTransformers
public TransformerManager(Instrumentation instrumentation) {this.instrumentation = instrumentation;classFileTransformer = new ClassFileTransformer() {@Overridepublic byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {for (ClassFileTransformer classFileTransformer : reTransformers) {byte[] transformResult = classFileTransformer.transform(loader, className, classBeingRedefined,protectionDomain, classfileBuffer);if (transformResult != null) {classfileBuffer = transformResult;}}for (ClassFileTransformer classFileTransformer : watchTransformers) {byte[] transformResult = classFileTransformer.transform(loader, className, classBeingRedefined,protectionDomain, classfileBuffer);if (transformResult != null) {classfileBuffer = transformResult;}}for (ClassFileTransformer classFileTransformer : traceTransformers) {byte[] transformResult = classFileTransformer.transform(loader, className, classBeingRedefined,protectionDomain, classfileBuffer);if (transformResult != null) {classfileBuffer = transformResult;}}return classfileBuffer;}};instrumentation.addTransformer(classFileTransformer, true);
}
以其中的Watcher为例子,看下Arthas底层是如何增强源码的;
//继承java.lang.instrument包中的 ClassFileTransformer 接口
public class Enhancer implements ClassFileTransformer {@Overridepublic byte[] transform(final ClassLoader inClassLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {//底层是ASMClassNode classNode = new ClassNode(Opcodes.ASM9);//首先获取原class对象ClassReader classReader = AsmUtils.toClassNode(classfileBuffer, classNode);classNode = AsmUtils.removeJSRInstructions(classNode);List<MethodNode> matchedMethods = new ArrayList<MethodNode>();for (MethodNode methodNode : classNode.methods) {if (!isIgnore(methodNode, methodNameMatcher)) {matchedMethods.add(methodNode);}}for (MethodNode methodNode : matchedMethods) {if (AsmUtils.isNative(methodNode)) {continue; //过滤调native方法}if(AsmUtils.containsMethodInsnNode(methodNode, Type.getInternalName(SpyAPI.class), "atBeforeInvoke")) {... //对class的方法添加watch功能}}return AsmUtils.toBytes(classNode, inClassLoader, classReader); //返回新的class对象}
}
相关文章:
从利用Arthas排查线上Fastjson问题到Java动态字节码技术(下)
上一篇从Arthas的源码引出了Java动态字节码技术,那么这一篇就从几种Java字节码技术出发,看看Arthas是如何通过动态字节码技术做到无侵入的源码增强; Java大部分情况下都是解释执行的,也就是解释.class文件,所以如果我们…...
Ubuntu中安装Anaconda 如何将 路径导入为全局变量
第一步:将你的anaconda 路径复制下来,在终端输入对应路径。 echo export PATH"/home/你的用户名/anaconda3/bin:$PATH" >> ~/.bashrc 第二步:在终端输入下面命令或者重启系统。 source ~/.bashrc 在对应的anaconda安装目…...
【QT】Qt的随身笔记(持续更新...)
目录 Qt 获取当前电脑桌面的路径Qt 获取当前程序运行路径Qt 创建新的文本文件txt,并写入内容如何向QPlainTextEdit 写入内容QTimerQMessageBox的使用QLatin1StringQLayoutC在c头文件中写#include类的头文件与直接写class加类名有何区别mutable关键字前向声明 QFontQ…...
【LeetCode-简单题】589. N 叉树的前序遍历
文章目录 题目方法一:单循环栈做法方法二:递归 题目 方法一:单循环栈做法 关键在于子节点的入栈顺序,决定了子节点的出栈顺序, 因为是前序遍历 所以压栈顺序先让右边的入栈 依次往左 这样左边的节点会在栈顶 这样下次…...
Linphone3.5.2 ARM RV1109音视频对讲开发记录
Linphone3.5.2 ARM RV1109音视频对讲开发记录 说明 这是一份事后记录,主要记录的几个核心关键点,有可能很多细节没有记上,主要是方便后面自己再找回来! 版本 3.5.2 一些原因选的是这样一个旧的版本! 新的开发最好选新一些的版…...
Unity用相机实现的镜子效果
首先登场 场景中的元素 mirror是镜子,挂着我们的脚本,Quad是一个面片。Camera是用来生成RenderTexture给面片的。里面的test1是我用来调试位置的球。 镜子size是大小,x是-2,为了反转一下贴图 相机直接可以禁用掉,用…...
计算机网络分类
按照覆盖范围分类 (1)个域网:通常覆盖范围在1~10m。 (2)局域网:通常覆盖范围在10m~1km。 (3)城域网:覆盖范围通常在5~50 km 。 &…...
AI AIgents时代 - (三.) AutoGPT和AgentGPT
前两篇讲解了Agent的原理和组件,这节我将给大家介绍两个agent项目,给出它们的工作原理和区别,并教大家亲手尝试使用 Agents🎉 🟢 AutoGPT🤖️ 我们的老朋友,之前文章也专门写过。AutoGPT 是一…...
Jmeter接口自动化和Python接口自动化,如何选择?
选择Jmeter或Python进行接口自动化测试取决于您的具体需求和环境。以下是一些可以考虑的因素: 1. 语言熟悉度:如果您对Java更熟悉,那么Jmeter可能是更好的选择。而如果您的团队或个人对Python更熟悉,那么Python可能是更好的选择。…...
Sqilte3初步教程
文章目录 安装创建数据库创建和删除表插入行数据 安装 Windows下安装,首先到下载页面,下载Windows安装软件,一般是 sqlite-dll-win32-*.zip sqlite-tools-win32-*.zip下载之后将其内容解压到同一个文件夹下,我把它们都放在了D:\…...
详解Python中的json库
目录 1. json简介2. dumps/loads3. dump/load4. jsonl格式 1. json简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,用于在不同应用程序之间传递数据。它是一种文本格式,易于阅读和编写,同时也易于…...
【Spring Boot】Spring Boot源码解读与原理剖析
这里写目录标题 前言精进Spring Boot首选读物“小册”变“大书”,彻底弄懂Spring Boot全方位配套资源,学不会来找我!技术新赛道,2023领先抢跑 前言 承载着作者的厚望,掘金爆火小册同名读物《Spring Boot源码解读与原理…...
C++学习(1)
一、C概述(了解) C在C语言的基础上添加了面向对象编程和泛型编程的支持 二、helloword程序(掌握) #define _CET_SECURE_NO_WARNINGS//在开发软件visual studio编译 c文件时, visual studio认为strcpy,scanf等函数不安全的导致报…...
机器人如何有效采摘苹果?
摘要:本文利用动捕数据构建拟人运动模型,对比观察两种苹果采摘模式,并对系统性能进行全面评估,为提高机器人采摘效率提供创新方法。 近期,一项关于苹果采摘机器人的有趣研究—— "Design and evaluation of a rob…...
C# OpenCvSharp Yolov8 Detect 目标检测
效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace Open…...
rust数组
一、定义数组 (一)一维数组 1.指定所有元素 语法格式 let variable_name: [dataType; size] [value1,value2,value3];例如 let arr: [i32; 4] [10,20,30,40];2.指定初始值和长度 所有元素具有相同的值 语法格式 let variable_name: [dataType; siz…...
ubuntu | 安装NVIDIA套件:驱动、CUDA、cuDNN
CUDA 查看支持最高的cuda版本 nvidia-smiCUDA Version:12.2 区官网下在12.2.x最新的版本即可CUDA Toolkit Archive | NVIDIA Developer 下载安装 wget https://developer.download.nvidia.com/compute/cuda/12.2.2/local_installers/cuda_12.2.2_535.104.05_linux.run sudo…...
JAVA学习笔记
一、学习要点 java的最大优势就是跨平台; java的三个版本,javaSE标准版本,javaEE企业版本,javaME微型版本(用的比较少); JVM(Java Virtual Machine,Java虚拟机); JRE…...
车载软件架构 —— 持续集成持续交付
车载软件架构 —— 持续集成持续交付 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 对学习而言,学习之后的思考、思考之后的行动、行动之后的改变更重要,如果不盯住内层的改变量,那么在表层投…...
c++ 二元运算符重载, 以加法为例
/* * c 二元运算符重载, 以加法为例 */ #include <stdio.h> class Complex { public: int r0; // real, 实部 int v0; //virtual, 虚部 }; // 重载加法 操作符 // 可见,c2元运算符,取其左侧为第一参数,右侧为第二参数 // 返回值可以付给新的变量 C…...
基于 SpringBoot+Vue的电影影城管理系统,附源码,数据库
文章目录 第一章 简介第二章 技术栈第三章 功能分析第四章 系统设计第5章 系统详细设计六 源码咨询 第一章 简介 本影城管理系统,是基于 Java SpringBoot 开发的。主要包括二大功能模块,即用户功能模块和管理员功能模块。 (1)管…...
Docker实战技巧(二):Kubernetes基础操作实战
Kubernetes定位在Saas层,重点解决了微服务大规模部署时的服务编排问题 1、关闭防火墙并设置开机禁用 systemctl stop firewalld systemctl disable firewalld 2、配置repo cd /etc/yum.repos.d/ 下载Docker repo wget https://mirrors.aliyun.com/docker-…...
计算机视觉与深度学习-循环神经网络与注意力机制-Attention(注意力机制)-【北邮鲁鹏】
目录 引出Attention定义Attention-based model通俗解释应用在图像领域图像字幕生成(image caption generation)视频处理 序列到序列学习:输入和输出都是长度不同的序列 引出Attention 传统的机器翻译是,将“机器学习”四个字都学…...
Centos7安装wps无法打开及字体缺失的问题解决
在centos7上安装了最新的wps2019版本的wps-office-11.1.0.11704-1.x86_64.rpm,生成了桌面图标并信任,可以新建文件,但是软件无法打开。在终端执行如下命令,用命令行启动wps: cd /opt/kingsoft/wps-office/office6/ ./…...
华为OD机试真题-会议接待-2023年OD统一考试(B卷)
题目描述: 某组织举行会议,来了多个代表团同时到达,接待处只有一辆汽车,可以同时接待多个代表团,为了提高车辆利用率,请帮接待员计算可以坐满车的接待方案,输出方案数量。 约束: 1、一个团只能上一辆车,并且代表团人数(代表团数量小于30,每个代表团人数小于30)小于…...
mysql explain学习记录
参考了公司内相关博客,实践并记录下,为后面分析并优化索引做准备。 MySQL explain命令是查看MySQL查询优化器如何执行查询的主要方法,可以很好的分析SQL语句的执行情况。 每当遇到执行慢(在业务角度)的SQL,…...
电压放大电路的作用有哪些(电压放大器)
电压放大电路是电子电路中常见且重要的组件,其主要作用是将输入信号的电压放大到所需的输出电压级别,并保持输入信号的形状和准确度。电压放大电路广泛应用于各种电子设备和系统中,具有以下几个重要的作用: 信号放大:电…...
编译opencv-3.4.5 [交叉编译]
在unbuntu20.04环境下编译opencv3.4.5, cmake 版本:3.27.4 gcc 版本:11.4.0 g版本:11.4.0 在此环境下编译opencv4.5.4正常。 1. 编译时遇到的问题 (1) Built target libprotobuf make: *** [Makefile:163…...
Canal 实现MySQL与Elasticsearch7数据同步
1 工作原理 canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送 dump协议 MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal ) canal 解析 binary log 对象(原始为 byte 流) 优点&…...
网络安全攻防对抗之隐藏通信隧道技术整理
完成内网信息收集工作后,渗透测试人员需要判断流量是否出得去、进得来。隐藏通信隧道技术常用于在访问受限的网络环境中追踪数据流向和在非受信任的网络中实现安全的数据传输。 一、隐藏通信隧道基础知识 (一)隐藏通信隧道概述 一般的网络通…...
网址建站/雷神代刷推广网站
1、 打开 MATLAB 软件,在命令窗口输入 fdatool 并回车,就会弹出滤波器设计工具 2、 FIR滤波器设计方法有多种,,最常用的是窗函数设计法(Window)、等波纹设计法(Equiripple)和最小二乘…...
百度推广免费送网站/常见的搜索引擎有哪些
大家好,欢迎回到 Java on Azure Tooling 的9月更新。在这次更新中,我们将介绍Azure Cosmos DB支持、Azure虚拟机增强管理。此外,我们还为用户创建/更新 Azure SDK Reference Book中的依赖库做了一些优化。请下载并安装我们的产品 Azure Toolk…...
网站建设招标公示/营销助手下载app下载
题意:给点一个无向图,求一个生成树使树中最大边与最小边的差的最小。 分析:并查集。把所有边排序,然后从小到大看,每次枚举一个边,将其权值作为下界,向右寻求一个上界,让上下界之间的…...
那个公司建设网站/海口百度seo公司
Debug 和 Release 编译方式的本质区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的&a…...
网站空间名词解释/网易最新消息新闻
伪原创是目前最鲜为人知的文章处理方式,做seo网站优化的也许知道,目前传统的文章伪原创方式的作用已经是越来越低了,所以我们文章在做伪原创时必须要提高伪原创文章的原创度,这样才能让搜索引擎更加信任我们,给我们的文…...
交互设计网站有哪些/如何做市场推广方案
217. 存在重复元素 给定一个整数数组,判断是否存在重复元素。 如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 示例 1: 输入: [1,2,3,1] 输出: true 示例 2: 输入: [1,2,3,4] 输出: false 示…...