99%的Java程序员不知道的Java Instrument

news2024/9/25 1:25:01

Java Instrumentation API 是一个强大的工具,它允许开发人员在运行时修改字节码,而无需重新编译或修改源代码。这对于性能监控、日志记录、安全审计等场景非常有用。本文将深入探讨Java Instrumentation的基础知识,并通过具体的代码示例来展示如何使用-javaagent选项以及premainagentmain方法来实现一些实用的功能。
在这里插入图片描述

Java Instrumentation简介

Java Instrumentation API 允许我们在应用程序启动之前(预主类)或者启动之后(代理主类)插入一些操作。这通常需要借助于JVM的一个参数-javaagent来指定一个代理(agent),该代理是一个实现了特定接口的jar文件。

使用-javaagent

要使用Instrumentation API,你需要在启动JVM时添加一个特殊的参数来指定agent的位置:

java -javaagent:/path/to/your-agent.jar=com.example.agent.YourAgent [app args]

这里com.example.agent.YourAgent是指定的premain类的全限定名。

premain方法

premain方法是在应用程序的主类执行之前调用的。这个方法可以用来初始化Instrumentation实例,并且允许你在这个阶段就对字节码进行修改。

public class YourAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("**YourAgent premain method called.**");

        // 添加Transformer来修改特定类的字节码
        inst.addTransformer(new YourClassFileTransformer());
    }
}

agentmain方法

agentmain方法允许你在应用程序已经启动之后,动态地加载agent。这可以通过Attach机制或者通过在启动时使用-javaagent参数同时指定agentmain类来实现。

public class YourAgent {
    public static void agentmain(String agentArgs, Instrumentation inst) {
        System.out.println("**YourAgent agentmain method called.**");
    }

    // 如果你想支持通过premain方式启动,也需要提供这个方法
    public static void premain(String agentArgs, Instrumentation inst) {
        agentmain(agentArgs, inst);
    }
}

示例:简单的字节码变换

让我们来看一个简单的例子,我们将会创建一个agent,它会在所有方法的开始处打印一条消息。

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class LoggingTransformer implements ClassFileTransformer {

    @Override
    public byte[] transform(ClassLoader loader, String className,
                            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
                            byte[] classfileBuffer) throws IllegalClassFormatException {
        
        try {
            // 只处理非系统类
            if (className.startsWith("java/") || className.startsWith("javax/")) {
                return null;
            }

            // 使用CtClass包装原始字节码
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.get(className.replace('/', '.'));
            
            // 遍历所有的方法
            for (CtMethod m : ctClass.getDeclaredMethods()) {
                // 在每个方法的开始处添加System.out.println
                m.insertBefore("{ System.out.println(\"Entering method: \" + this.getClass().getName() + \".\" + $sig); }");
            }
            
            return ctClass.toBytecode();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

为了使上述变换器工作,我们需要在YourAgent类中注册它:

public class YourAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new LoggingTransformer());
    }
}

Attach机制概述

Attach机制允许一个外部程序(例如一个命令行工具或另一个Java应用)连接到正在运行的JVM上,并动态地加载一个agent。这种能力对于诊断和调试正在运行的应用程序特别有用。

如何Attach到远程JVM

要Attach到一个本地或远程的JVM,你需要使用jattach工具(从JDK 7开始包含在内)或者使用sun.tools.attach包中的API。下面是一个使用jattach工具附加到本地JVM的例子:

jattach <pid> loadagent:/path/to/your-agent.jar

这里的<pid>是你要附加的目标JVM的进程ID。

使用agentmain进行动态加载

如果想要在程序运行时动态加载agent,你需要确保你的agent实现了agentmain方法。下面是一个简单的例子:

public class DynamicAgent {
    
    /**
     * 在agent被动态加载时调用的方法
     * @param agentArgs 代理参数
     * @param inst      Instrumentation实例
     */
    public static void agentmain(String agentArgs, Instrumentation inst) {
        System.out.println("**DynamicAgent agentmain method called.**");
        // 这里可以添加任何需要的字节码转换逻辑
        inst.addTransformer(new DynamicTransformer(), true);
    }
    
    /**
     * 如果agent通过premain方式启动,也必须提供这个方法
     * @param agentArgs 代理参数
     * @param inst      Instrumentation实例
     */
    public static void premain(String agentArgs, Instrumentation inst) {
        agentmain(agentArgs, inst);
    }
}

class DynamicTransformer implements ClassFileTransformer {
    @Override
    public byte[] transform(ClassLoader loader, String className,
                            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
                            byte[] classfileBuffer) throws IllegalClassFormatException {
        // 实现字节码转换逻辑
        return classfileBuffer; // 返回未修改的字节码作为示例
    }
}

通过Attach API动态加载agent

除了使用jattach命令行工具之外,你也可以编写代码来使用java.lang.management包中的RuntimeMXBean来Attach到目标JVM,并调用VirtualMachine.loadAgent方法来加载agent。

以下是一个简单的示例,展示了如何使用Attach API来动态加载agent:

import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

public class AttachExample {
    public static void main(String[] args) {
        try {
            // 获取所有可连接的JVM描述符
            VirtualMachineDescriptor[] descriptors = VirtualMachine.list();

            // 假设我们要连接的是第一个找到的JVM
            VirtualMachine vm = VirtualMachine.attach(descriptors[0].id());

            // 加载agent
            vm.loadAgent("/path/to/your-agent.jar");

            // 关闭连接
            vm.detach();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意,com.sun.tools.attach.*包是平台特定的,因此这段代码可能需要根据你的Java版本和操作系统进行调整。此外,在生产环境中使用Attach功能时,应该小心处理权限和安全性问题。

以上就是关于如何使用agentmain方法结合Attach机制来动态加载Java agent的基本信息。这种方法提供了极大的灵活性,但也要求开发者熟悉底层细节和相关的安全考量。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【全网最全】2024年数学建模国赛C题超详细保奖思路+可视化图表+成品论文+matlab/python代码等(后续会更新

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片&#xff0c;那是获取资料的入口&#xff01; 基于优化模型的农作物的种植策略 摘要 随着农业生产向集约化和智能化方向发展&#xff0c;优化种植策略以最大化经济收益成为当前农业研究中的重要问题。本…

828华为云征文|部署个人博客管理系统 Ghost

828华为云征文&#xff5c;部署个人博客管理系统 Ghost 一、Flexus云服务器X实例介绍1.1 云服务器介绍1.2 应用场景1.3 对比普通ECS 二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 Ghost3.1 Ghost 介绍3.2 Docker 环境搭建3.3 Ghost 部署3.4 …

记一次mysql锁等待超时问题

背景 如图所示&#xff0c;一个简单的删除语句&#xff0c;抛出了Lock wait timeout exceeded; try restarting transaction异常&#xff0c;查询这条记录&#xff0c;并尝试修改这条记录&#xff0c;发现修改操作都被hang住了 原因 待补充 解决方法 在mysql里&#xff0c…

营养三餐轻松搭配:健康生活从早餐开始

在如今的快节奏生活中&#xff0c;健康饮食与快捷管用的减调计划&#xff0c;已成为了许多人关注的焦点。合理的三餐搭配不仅能帮助我们控制形体&#xff0c;还能提升生活质量。今天&#xff0c;就让我们一起来学习一套科学的三餐减调套餐&#xff0c;让你在享受美食的同时&…

tuya open-sdk 1.0.0 发布

我们很高兴地宣布本次更新&#xff0c;带来了多项改进和新功能&#xff0c;旨在提升开发体验和效率。以下是具体更新内容&#xff1a; 代码标准化&#xff1a;实现了代码库的格式统一&#xff0c;引入了 clang-format 和 pre-commit 工具进行自动化代码格式调整&#xff0c;确保…

Docker 配置国内镜像源

由于 GFW 的原因&#xff0c;在下载镜像的时候&#xff0c;经常会出现下载失败的情况&#xff0c;此时就可以使用国内的镜像源。 什么是镜像源&#xff1a;简单来说就是某个组织&#xff08;学校、公司、甚至是个人&#xff09;先通过某种手段将国外的镜像下载下来&#xff0c;…

AI时代来临,AI基础数据服务行业未来发展有哪些变化

AI基础数据服务是针对人工智能&#xff08;AI&#xff09;领域提供的一项服务&#xff0c;它包括数据采集、数据清洗、信息抽取和数据标注等服务。AI基础数据服务旨在为AI算法的训练和优化提供必要的数据支持&#xff0c;为AI算法的性能提供保障。 标贝科技提供专业的数据采集、…

前端自查【知识点】(高概率)2024最新版

HTML 如何理解 HTML 语义化 ? 仅通过标签便能判断内容的类型&#xff0c;特别是区分标题、段落、图片和表格 增加代码可读性&#xff08;让人更容易读懂&#xff09;对SEO更加友好 &#xff08;让搜索引擎更容易读懂&#xff09; HTML有哪些内联元素和块状元素 ? 内联元素…

拌合站智能管理系统,如何实现智能化生产管理?

随着基础设施建设的不断推进&#xff0c;拌合站作为混凝土生产的重要环节&#xff0c;其管理水平直接影响到工程质量和施工效率。然而&#xff0c;传统的拌合站管理方法存在一些问题&#xff0c;如生产效率低、质量控制难、资源浪费等。在信息化和智能化技术迅猛发展的今天&…

4个工具帮你轻松实现视频在线压缩。

视频已经成了大家生活中很重要的一部分&#xff0c;能够帮助我们记录很多重要的东西&#xff0c;哟其实视频内容创作者&#xff0c;各种素材特别多。可使&#xff0c;随着视频越拍越多&#xff0c;设备的空间也会越来越紧张。所以&#xff0c;这次要为大家推荐4个专业的视频在线…

天翼云,AI取经路上的逐梦人

最近&#xff0c;国产第一部3A游戏大作《黑神话&#xff1a;悟空》问世&#xff0c;引发了全网热潮。游戏中的主角&#xff0c;重走西游之路&#xff0c;克服重重难关&#xff0c;向世界展现了中国文化的绝美与中国科技的自信。 而在现实当中&#xff0c;通往产业智能化的AI之路…

JVM系列(八) -运行期的几种优化技术

一、摘要 在之前的文章中我们谈到过,相比 C/C++ 语言,Java 语言在运行效率方面要稍逊一些,因为 Java 应用程序是在虚拟机上运行,而 C/C++ 程序是直接编译成平台相应的机器码来运行程序。 从虚拟机对外发布开始,开发团队一直在努力试图缩小 Java 与 C/C++ 语言在运行效率…

去除视频水印字幕从未如此简单!4款神器助你轻松搞定!

文章介绍的四款工具都已经打包好了,文末关注公众号AIshape 回复 “视频去水印” 获取 我们平时在各大视频网站下载的视频一般都会带有平台的logo水印,像Runway、Pika、即梦、可灵等AI视频生成平台创作的视频素材,非会员下载会带有水印 想利用这些视频素材进行二次创作很不方…

glsl着色器学习 (十二)平移

平移和旋转、缩放是一样的&#xff0c;替换成平移矩阵即可&#xff1b; // 创建一个单位矩阵 const translateYMatrix mat4.create();// 沿着Y轴向下平移1个单位 mat4.fromTranslation(translateYMatrix, [0, -1, 0]);// 设置矩阵 gl.uniformMatrix4fv(matrixUniformLocation…

Maven学习与使用

内容概要 Maven是什么&#xff0c;有什么作用会配置Maven的环境&#xff0c;以及在idea上配置&#xff08;重点&#xff09;掌握Maven的工程结构掌握Maven的几个重要指令。&#xff08;clean compile package install&#xff09;掌握如何导包及依赖冲突解决办法 1 Maven 1.…

超详细!!!最新的VuePress + Github Pages + Github Actions实现博客自动部署

超详细&#xff01;&#xff01;&#xff01;VuePress Github Pages Github Actions实现博客自动部署 本文着重讲述如何使用通过Github Actions将VuePress项目部署自动在Github Pages上。每一位开发者有一个自己的博客网站是一件很酷的事情&#xff0c;由于最近想整理一下在…

SpringBoot学习(8)(Bean注册条件)(@Conditional的衍生注解)

目录 一、引言 二、案例引用&#xff08;接着上篇博客&#xff09; 三、注册条件 &#xff08;1&#xff09;ConditionalOnProperty &#xff08;2&#xff09;Conditional0nMissingBean &#xff08;3&#xff09;ConditionalOnclass 四、总结 一、引言 之前学习和了解了Bean对…

相亲交友系统商业开发

在快节奏的现代生活中&#xff0c;寻找真爱成为了许多人的渴望。相亲交友系统&#xff0c;作为连接心灵的桥梁&#xff0c;正逐渐成为人们寻找伴侣的首选方式。我们的团队h17711347205致力于开发一款创新的相亲交友系统&#xff0c;旨在通过智能化的匹配算法&#xff0c;为用户…

出门总是一身猫毛怎么办?霍尼韦尔、希喂、352、小米宠物空气净化器对比实测

毕业了好些年&#xff0c;前段时间有同学组织了聚会&#xff0c;聚一聚&#xff0c;我们班的专业本身就和动物有关&#xff0c;聊天自然而然聊到了宠物上去&#xff0c;有个同学打趣&#xff1a;“有没有养猫狗看看衣服就知道了”。还真是家里养了宠物的&#xff0c;无论咋清理…

电子商务小程序如何做seo

电子商务小程序进行SEO&#xff08;搜索引擎优化&#xff09;是一个综合性的过程&#xff0c;旨在提高小程序在搜索引擎中的排名&#xff0c;从而增加曝光度和用户流量。以下是一些关键的SEO策略和实践方法&#xff1a; 电子商务小程序如何做seo 1. 关键词研究与布局 关键词选…