pinpoint字节码增强技术原理

字节码的终极应用-GitHub高星开源APM项目之Pinpoint 本文我们介绍了一个开源的APM分布式链路监控工具Pinpoint.主要介绍了Pinpoint的架构和特点, 随后我们使用几个简单的demo模拟分布式调用的场景, 和大家一起分析了java应用采集到的各种监控指标, 主要分为Metric(指标数据)和Trace(请求数据). 希望对大家排查问题有一定的帮助.方法燃尽图是从方法的维度看某一次请求的耗时情况, 从该图中我们可以清洗的看到调用了哪些方法, 他们的耗时是多少. 对于业务开发人员来说, 通常可以一眼就看出哪些方法的耗时偏高. 阅读详情

pinpoint通过字节码增加技术(有的叫动态探针技术)来实现无侵入式的调用链采集。其核心实现原来还是基于JVM的javaagent机制来实现。pinpoint在启动时通过设置

-javaagent:$AGENT_PATH/pinpoint-bootstrap-$VERSION.jar

来指定pinpoint agent加载路径,在启动的时候agent将在加载应用class文件之前做拦截并修改字节码,在class方法调用的前后加上链路采集逻辑,从而实现链路采集功能。

javaAgent的底层机制主要依赖JVMTI ,JVMTI全称JVM Tool Interface,是JVM暴露出来的一些供用户扩展的接口集合。JVMTI是基于事件驱动的,JVM每执行到一定的逻辑就会调用一些事件的回调接口(如果有的话),这些接口可以供开发者扩展自己的逻辑。但JVMTI都是一些接口合集,需要有接口的实现,这就用到了java的instrument,可以理解instrument是JVMTI的一种实现,为JVM提供外挂支持。

instrument支持启动时加载和运行时加载两种方式,分别实现JVMTI的Agent_OnLoad和Agent_OnAttach方法;pinpoint目前采用的是启动时加载方式,下面我来看pinpoint是如何实现启动时修改应用字节码的:

1. Pinpoint Agent 类必须打成jar包,然后里面的 META-INF/MAINIFEST.MF 必须包含 Premain-Class这个属性

Manifest-Version: 1.0
Premain-Class: com.navercorp.pinpoint.bootstrap.PinpointBootStrap
Archiver-Version: Plexus Archiver
Built-By: user
Can-Redefine-Classes: true
Pinpoint-Version: 1.6.0-SNAPSHOT
Can-Retransform-Classes: true
Created-By: Apache Maven 3.5.2
Build-Jdk: 1.8.0_152

2. 启动类中实现instrument规定的premain方法(PinpointBootStrap.java),应用在启动前会优先调用这个方法。

    public static void premain(String agentArgs, Instrumentation instrumentation) {
        if (agentArgs == null) {
            agentArgs = "";
        }
        logger.info(ProductInfo.NAME + " agentArgs:" + agentArgs);

        final boolean success = STATE.start();
        if (!success) {
            logger.warn("pinpoint-bootstrap already started. skipping agent loading.");
            return;
        }
        Map<String, String> agentArgsMap = argsToMap(agentArgs);

        final ClassPathResolver classPathResolver = new AgentDirBaseClassPathResolver();
        if (!classPathResolver.verify()) {
            logger.warn("Agent Directory Verify fail. skipping agent loading.");
            logPinpointAgentLoadFail();
            return;
        }

        BootstrapJarFile bootstrapJarFile = classPathResolver.getBootstrapJarFile();
        appendToBootstrapClassLoader(instrumentation, bootstrapJarFile);


        PinpointStarter bootStrap = new PinpointStarter(agentArgsMap, bootstrapJarFile, classPathResolver, instrumentation);
        if (!bootStrap.start()) {
            logPinpointAgentLoadFail();
        }

    }

agentArgs 是 premain 函数得到的程序参数,随同 “-javaagent”一起传入。与 main 函数不同的是,这个参数是一个字符串而不是一个字符串数组,如果程序参数有多个,程序将自行解析这个字符串;pinpoint中的agentArgs就是pinpoint的jar包。

instrumentation 是一个 java.lang.instrument.Instrumentation 的实例,由 JVM 自动传入。java.lang.instrument.Instrumentation 是 instrument 包中定义的一个接口,也是这个包的核心部分,集中了其中几乎所有的功能方法,例如类定义的转换和操作等等。

3. 跟踪premain代码主要调用PinpointStarter.start()方法

    boolean start() {
        /**省略代码*/

        try {
            // Is it right to load the configuration in the bootstrap?
            ProfilerConfig profilerConfig = DefaultProfilerConfig.load(configPath);

            // this is the library list that must be loaded
            List<URL> libUrlList = resolveLib(classPathResolver);
            AgentClassLoader agentClassLoader = new AgentClassLoader(libUrlList.toArray(new URL[libUrlList.size()]));
            final String bootClass = getBootClass();
            agentClassLoader.setBootClass(bootClass);
            logger.info("pinpoint agent [" + bootClass + "] starting...");

            AgentOption option = createAgentOption(agentId, applicationName, profilerConfig, instrumentation, pluginJars, bootstrapJarFile, serviceTypeRegistryService, annotationKeyRegistryService);
            Agent pinpointAgent = agentClassLoader.boot(option);
            pinpointAgent.start();
            registerShutdownHook(pinpointAgent);
            logger.info("pinpoint agent started normally.");
        } catch (Exception e) {
            // unexpected exception that did not be checked above
            logger.warn(ProductInfo.NAME + " start failed.", e);
            return false;
        }
        return true;
    }

4. 继续跟踪代码主要调用pinpointAgent.start()方法,而pinpointAgent在此处的实现类是DefaultAgent.

   public DefaultAgent(AgentOption agentOption, final InterceptorRegistryBinder interceptorRegistryBinder) {

        /**省略代码*/

        this.profilerConfig = agentOption.getProfilerConfig();
        this.instrumentation = agentOption.getInstrumentation();
        this.agentOption = agentOption;

        //默认使用ASM字节码引擎
        this.classPool = createInstrumentEngine(agentOption, interceptorRegistryBinder);

        if (logger.isInfoEnabled()) {
            logger.info("DefaultAgent classLoader:{}", this.getClass().getClassLoader());
        }

        //加载转换class字节码逻辑的插件,主要逻辑是将各个插件需要转换的目标class拦截器(拦截器是pinpoint自身封装的一类方法)存入List<ClassFileTransformer>中
        pluginContexts = loadPlugins(agentOption);
        //将List<ClassFileTransformer>转成HashMap<className,ClassFileTransformer>
        this.classFileTransformer = new ClassFileTransformerDispatcher(this, pluginContexts);
        this.dynamicTransformService = new DynamicTransformService(instrumentation, classFileTransformer);

        ClassFileTransformer wrappedTransformer = wrapClassFileTransformer(classFileTransformer);
        //调用jvm instrumentation工具方法
        instrumentation.addTransformer(wrappedTransformer, true);


        /**省略代码*/
    }

可以看出,addTransformer 方法并没有指明要转换哪个类,此时并未发生实际的字节码转换。转换发生在 premain 函数执行之后,main 函数执行之前,这时每装载一个类,transform 方法就会执行一次,看看是否需要转换,此时wrappedTransformer最终会通过dynamicTransformService封装的HashMap<className,classFileTransformer>来判断当前加载的应用类是否需要转换。

最后我们通过一幅图来展示pinpoint的字节码转换过程:

1. JVM初始化并通过System ClassLoader加载Pinpoint Agent类;创建Instrumentation接口实例并调用Pinpoint Agent的Premain方法,并自动传入Instrumentation实例;

2. Pinpoint Agent加载plugins插件,将其中的transformer类注册到Instrumentation实例中;

3. System ClassLoader加载其他的应用Java类,此时将调用注册的transformer方法对要加载的java类进行字节码转换;

4. JVM将转换后的class放入方法区。

 

参考文章:

Instrumentation 新功能

JVM源码分析之javaagent原理完全解读

JVM Attach机制实现

Windows Server远程桌面断开后,PyWinAuto/按键精灵脚本失效?试试这个‘会话保持’的终极配置 本文深入解析Windows Server远程桌面断开后导致PyWinAuto/按键精灵脚本失效的问题,提供会话保持的终极配置方案。通过转换到控制台会话(console模式)和调整组策略,确保自动化程序在断开连接后持续稳定运行,适用于Windows Server各版本。 阅读详情

相关推荐

Rockchip平台之RK3566/3568 OS02N10

文章摘要 本文主要介绍了200W摄像头传感器OS02N10在RK3566平台上的兼容与适配过程。作者基于之前的400W摄像头兼容经验,针对200W摄像头进行了类似的适配工作。文章详细阐述了RK3566芯片的特性和OS02N10传感器的技术参数,包括分辨率、接口和功耗等。适配过程分为三个关键部分:DTS设备树文件配置(定义I2C地址、电源域和GPIO控制等)、驱动文件开发(寄存器初始化和操作)以及XML和JSON配置文件调整(图像参数设置)。作者特别强调了初始化数组中空寄存器终止条件的重要性,并分享了兼容过程

different_xzh的博客 2412

全链路监控之pinpoint

一、pinpoint出现与其他相似概念比较 (1)、pinpoint概念 pinpoint是由java/PHP编写而成的,用来对大规模的分布式系统提供应用性能管理。pinpoint可以解决复杂架构下的拓扑解析与性能分析。 (2)、pinpoint的特点 分布式事务追踪,跟踪跨分布式应用的消息; 自动检测拓扑,帮助搞清楚应用架构; 水平扩展可以支持大规模服务器集群; 提供代码级别的可见性,轻松定位失败点和瓶颈; 使用字节码增强技术,添加新功能是无需修改代码...

Romanticn_chu的博客 8982

S32K3双核实战:手把手教你用EB配置CAN与CANFD(附中断/轮询代码对比)

本文详细解析了NXP S32K3双核处理器在CAN/CANFD通信开发中的实战应用。通过Elektrobit配置工具链,从双核通信架构设计到EB tresos Studio配置全流程,再到中断与轮询模式的代码实现对比,全面指导开发者优化S32K3 FlexCAN模块性能,提升汽车电子系统的通信效率与可靠性。

weixin_30955617的博客 440

分布式链路追踪工具pinpoint采样率原理分析

前言一系列的服务上云后,可能分布在几千甚至几万台服务器上,服务与服务之间存在大量复杂的调用关系,而pinpoint在采集这些服务数据时,同样会产生大量的报文。在naver公司的在线门户服...

独行侠梦的博客 4887

Windows下快速搭建Kettle开发环境:基于9.4.0.0版本的保姆级教程

本文提供Windows系统下Kettle 9.4.0.0开发环境的详细搭建指南,涵盖源码获取、Maven配置优化、高效编译及部署运行全流程。通过实战验证的步骤和常见问题解决方案,帮助数据工程师快速完成环境配置,提升ETL开发效率。

weixin_28829479的博客 332

从零搭建openEuler ARM64开发测试环境:手把手教你用libvirt+KVM配置虚拟机(含VNC远程安装)

本文详细介绍了如何在ARM64平台上从零搭建openEuler开发测试环境,涵盖libvirt和KVM配置虚拟机的完整流程,包括环境准备、存储配置、网络优化、XML配置详解以及VNC远程安装。特别针对华为欧拉(openEuler)系统进行了优化,帮助开发者快速构建高效的ARM架构虚拟化环境。

weixin_30545945的博客 587

Pingpoint 技术详解

英文原文:https://naver.github.io/pinpoint/1.8.4/techdetail.html 说明:【】中内容为方便解释自己加的 在这篇文章中,我们描述了Pinpoint的技术细节比如请求追踪(transaction tracing)和字节码插装(bytecode instrumentation),同时说明了应用于Pinpoint agent中的优化方法,它可以修改字节码...

zlp1992的专栏 1万+

无人机避障——Mid360+Fast-lio感知建图+Ego-planner运动规划(胎教级教程)

本工作将 Mid360 激光雷达、Fastlio-SLAM 和 Ego-Planner 集成,实现无人机的环境感知、定位建图和运动规划(仿真过程)—— 胎教级教程。

weixin_45390670的博客 1万+

Pinpoint(三)字节码增强技术原理

pinpoint通过字节码增加技术(有的叫动态探针技术)来实现无侵入式的调用链采集。其核心实现原来还是基于JVM的javaagent机制来实现。pinpoint在启动时通过以下命令来指定pinpoint agent加载路径,在启动的时候agent将在加载应用class文件之前做拦截并修改字节码,在class方法调用的前后加上链路采集逻辑,从而实现链路采集功能。 -javaagent:$AGEN...

傅红雪的专栏 1680

线性代数——(期末突击)行列式(上)-行列式计算、行列式的性质

简单解释一下:4213原本的顺序应为1234,对于‘4’而言,‘2’、‘1’、‘3’都应该排在它的前面,所以此处记逆序数为3;对于‘2’而言,‘1’应该排在它的前面,而‘3’排在它之后 是合理的,所以此处只有一个逆序数;最后看‘1’,其后面的‘3’排在后面显然也是合理的,故而4213的逆序数为4.一般我们使用这个性质来计算四阶行列式,也就是将其变换成三角行列式,再计算对角线的值;以主对角线为分界线的就为正三角,反之则为反三角行列式。若行列式某一行(列)为0,则该行列式=0.将和的那一行分开,其余行。

li13437542099的博客 1万+

告别理论劝退:用动画和Tanner图轻松理解QC-LDPC的译码原理(BP算法详解)

本文通过动画和Tanner图直观解析QC-LDPC码的BP译码原理,帮助读者轻松理解802.11ac协议中的编译码过程。文章详细展示了QC-LDPC的结构之美、BP算法的动态信息流动以及LLR的视觉化解读,并对比了硬判决算法的性能差异,为开发者和研究者提供了实用的可视化工具开发建议。

weixin_30411239的博客 493

分布式链路追踪架构设计及核心技术原理

胡弦,视频号2023年度优秀创作者,互联网大厂P8技术专家,Spring Cloud Alibaba微服务架构实战派(上下册)和RocketMQ消息中间件实战派(上下册)的作者,资深架构师,技术负责人,极客时间训练营讲师,四维口袋KVP最具价值技术专家,技术领域专家团成员,2021电子工业出版社年度优秀作者,获得2023电子工业出版技术成长领路人称号,荣获2024年电子工业出版社博文视点20周年荣誉专家称号,2024电子工业出版社年度优秀作者。

huxian1234的专栏 2164

对偶分解算法详解及其Python实现

对偶分解算法是一种广泛应用于求解凸优化问题的有效方法,尤其在大规模数据处理和分布式计算中展现出强大的实用性。在许多实际应用中,直接求解原始问题可能由于计算复杂度过高、资源受限或问题规模过大而变得不可行。这时,对偶分解方法为我们提供了一种高效的替代方案。对偶分解算法的核心思想是将复杂的原问题转化为其对应的拉格朗日对偶问题。通过引入拉格朗日乘子并构造对偶函数,该方法在一定程度上简化了问题的求解过程。特别是,对于包含多个约束条件的大规模优化问题,对偶分解可以将原问题分解为若干个小规模、相互独立的子问题。

闲人编程的博客 1754

Pinpoint Agent字节码增强调试Docker:多阶段构建

在分布式系统开发中,你是否经常遇到服务性能瓶颈却难以定位?是否在排查跨服务调用问题时感到无从下手?Pinpoint Agent作为一款强大的APM(应用性能监控)工具,通过字节码增强技术实现无侵入式监控,帮助开发者深入了解应用运行时状态。本文将详细介绍如何使用Docker多阶段构建优化Pinpoint Agent的调试流程,让你在5分钟内掌握从构建到调试的全流程。 ## 一、Docker多阶段构...

gitblog_00212的博客 984

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

论文自动改进循环:基于 ARIS 的 Review → Fix → Recompile 两轮打磨实战指南

> 本指南聚焦 ARIS 项目中 `auto-paper-improvement-loop` 这一核心技能(位于 [skills/auto-paper-improvement-loop/SKILL.md](https://link.gitcode.com/i/954665bc8adbef98b07833b979be269b))。它以「外部 LLM 评审 → 按优先级修复 → 重新编译」为核心闭环,

gitblog_00728的博客 949

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

3%性能损耗实现全链路追踪:Pinpoint Agent字节码增强黑科技解密

你是否遇到过这些困扰?分布式系统故障排查时像大海捞针,线上问题定位需要修改代码埋点,性能监控工具本身反而拖慢系统?Pinpoint Agent通过字节码增强技术,实现了零代码侵入的全链路追踪,性能损耗仅约3%。本文将深入浅出解析其核心原理,读完你将了解: - 字节码增强如何实现无侵入监控 - Pinpoint Agent的工作流程与核心组件 - 插件化架构如何适配不同框架 - 实际应用中的性能优化...

gitblog_01149的博客 905

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Pinpoint Agent字节码增强调试环境:远程调试配置

在分布式系统开发中,你是否曾遇到过生产环境中难以复现的性能问题?Pinpoint作为一款优秀的APM(Application Performance Management)工具,通过Agent字节码增强技术实现无侵入式监控。然而,当Agent本身出现异常或需要定制化开发时,如何搭建高效的调试环境成为开发者面临的主要挑战。本文将详细介绍如何配置Pinpoint Agent的远程调试环境,帮助你快速定...

gitblog_00004的博客 787

Pinpoint Agent字节码增强安全扫描:SAST工具集成完整指南

Pinpoint是一款强大的开源APM(应用性能监控)工具,通过字节码增强技术实现分布式系统的跟踪与分析。本指南将详细介绍如何利用Pinpoint Agent的字节码增强能力,构建安全的SAST(静态应用安全测试)扫描流程,帮助开发团队在早期发现潜在的安全漏洞。 ## 什么是Pinpoint Agent字节码增强? Pinpoint Agent通过Java字节码增强技术,在不修改应用源代码的情

gitblog_00294的博客 1029

零侵入监控革命:Pinpoint Agent字节码注入技术深度剖析

当线上服务响应变慢时,你是否经历过这些困境:想排查问题却发现监控工具需要修改应用代码?接入性能分析工具后反而引发新的性能问题?Pinpoint Agent的无侵入式设计彻底解决了这些痛点。本文将带你揭开字节码注入技术的神秘面纱,了解如何在不修改一行业务代码的情况下,实现对分布式系统的全链路追踪。 读完本文你将掌握: - 无侵入式监控的核心实现原理 - 字节码注入技术在Pinpoint中的应用 -...

gitblog_01150的博客 988

Pinpoint Agent字节码增强代码生成工具:模板引擎实现

在分布式系统开发中,你是否还在为应用性能追踪的埋点侵入性而烦恼?是否因手动编写字节码增强代码效率低下而头疼?Pinpoint Agent的字节码增强代码生成工具,通过灵活的模板引擎实现,可帮助你轻松解决这些问题。读完本文,你将了解该工具的核心实现原理、模板引擎工作流程以及如何利用它进行高效的字节码增强开发。 ## 核心实现架构 Pinpoint Agent的字节码增强代码生成工具基于ASM框架...

gitblog_00416的博客 309

Application Performance Management工具之pinpoint

1.背景知识Application Performance Management是什么?维基百科: In the fields of information technology and systems management, Application Performance Management (APM) is the monitoring and management of perfor

neven7的专栏 1万+

Pinpoint调研

笔记 介绍 Pinpoint是一个大型分布式系统的n层架构跟踪平台。特点有五: 分布式事物跟踪用于跟踪分布式应用的消息; 自动检测应用拓扑帮助理解应用架构; 可水平扩展支持大规模集群; 提供代码级可见功能以便发现问题点和瓶颈; 字节码增强技术添加功能无需修改代码。 分布式事物跟踪 基于Google的Dapper论文。Dapper对rpc插桩传递span id和trace id,Pinpoin...

lzshlzsh的专栏 820

PinPoint调研

PinPoint简介 何为pinpoint: pinpoint是一个分析大型分布式系统的平台,提供解决方案来处理海量跟踪数据,主要面向基于tomcat的Java 应用。 为何使用它:和如今相比, 过去的因特网的用户数量相对较小,而因特网服务的架构也没那么复杂。web服务通常使用两层(web 服务器和数据库)或三层(web服务器,应用服务器和数据库)架构。然而在如今,随着互联网的成长,需要支持大量的并发连接,并且需要将功能和服务有机结合,导致更加复杂的软件栈组合。更确切地说,比三层层次更多的n层架构变得更

Sodawyx的博客 343

初探Pinpoint Agent 启动源码

Pinpoint通过字节码增强技术来实现无侵入式的调用链采集。其核心实现是基于JVM的Java Agent机制。 我们使用Pinpoint时,需要在Java应用启动参数上加上-javaagent:$AGENT_PATH/pinpoint-bootstrap-$VERSION.jar参数,这样,当我们的Java应用启动时,会同时启动Agent。 Pinpoint Agent在启动的时候,会加载plugin文件夹下所有的插件,这些插件会对特定class类修改字节码,在一些指定的方法调用前后加上链路采集逻辑

未完成的空间 2856

【Spring】Spring Cloud 链路追踪:SkyWalking/Pinpoint 字节码增强与 TraceId 传递机制

Spring Cloud 链路追踪技术解析 本文深入剖析了 SkyWalking 和 Pinpoint 在 Spring Cloud 环境中的链路追踪实现机制。两种方案均采用 Java Agent 技术实现无侵入式埋点,通过字节码增强动态注入追踪逻辑,但在实现策略和性能表现上存在差异。 核心内容包括: 字节码增强机制:对比 SkyWalking 基于 ByteBuddy/ASM 的动态插件架构与 Pinpoint 的静态插件实现 TraceId 传递:详解跨进程(HTTP/RPC)和跨线程(异步场景)的上下

瘦到被风吹走的博客 762

Pinpoint 源码分析(一)

pinpoint 是什么? 这个问题还是详见官方文档,我写得应该不会比它更好了。 原文:https://github.com/naver/pinpoint/wiki/Technical-Overview-Of-Pinpoint 译文:https://github.com/skyao/learning-pinpoint/blob/master/design/technical_overview.m...

weixin_39429729的博客 2133
上一篇: 记一次pinpoint内存占用过多故障排查
下一篇: ElasticSearch写入性能优化
wang_wpw
博客等级 码龄18年 4粉丝 2原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值