news 2026/6/10 16:30:45

大模型应用监控不内卷!Java Agent带你躺平实现无侵入监控

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
大模型应用监控不内卷!Java Agent带你躺平实现无侵入监控

应用场景

  • APM:应用性能监控。如 SkyWalking、OpenTelemetry 等通过 Agent 插桩收集调用链、耗时等
  • 代码覆盖率工具:如 JaCoCo 在测试时注入探针统计覆盖情况
  • 热部署 / 热更新:如 JRebel 利用 Agent 修改类定义实现无需重启生效
  • 安全审计 / 日志增强:自动为敏感方法添加日志或权限检查
  • 故障注入 / 混沌工程:动态修改行为模拟异常

静态加载示例

时机

在目标程序的 main() 入口方法之前执行

加载方式

通过添加 JVM 参数【-javaagent:Agent-Jar包全路径=参数】 来加载

参数的格式一般使用【key1=value1,keyN=valueN】

类加载状态

所有应用类都尚未加载,Agent 有完全的控制权

能力

可以执行任意字节码转换,包括添加字段、方法等

重启要求

需要重启 JVM

代码与运行示例

Agent模块:依赖坐标

<dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.17.8</version> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.17.8</version> </dependency>

Agent模块:pom.xml 插件配置

<build> <plugins> <!-- Java Agent插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.6.1</version> <executions> <execution> <!-- 插件在打包时才执行 --> <phase>package</phase> <!-- 插件执行时执行maven-shade-plugin的shade操作 --> <goals> <goal>shade</goal> </goals> <configuration> <!-- 不生成精简pom文件,保持完整的依赖树 --> <createDependencyReducedPom>false</createDependencyReducedPom> <transformers> <!-- 生成jar包时,添加Agent需要的MANIFEST.MF条目 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 入口配置 --> <manifestEntries> <!-- 静态加载Agent的入口类 --> <Premain-Class>wxw.mengyuan.DemoAgent</Premain-Class> <!-- 动态加载Agent的入口类 --> <Agent-Class>wxw.mengyuan.DemoAgent</Agent-Class> <!-- 允许重转换已加载类 --> <Can-Retransform-Classes>true</Can-Retransform-Classes> <!-- 允许重新定义类结构 --> <Can-Redefine-Classes>true</Can-Redefine-Classes> <!-- 设置native方法前缀 --> <Can-Set-Native-Method-Prefix>false</Can-Set-Native-Method-Prefix> </manifestEntries> </transformer> <!-- 合并所有依赖中 META-INF/services 目录下的文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <!-- 排除数字签名文件 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <!-- 重命名依赖避免冲突 --> <relocations> <relocation> <pattern>com.google</pattern> <shadedPattern>com.yourcompany.shaded.google</shadedPattern> </relocation> <relocation> <pattern>org.apache</pattern> <shadedPattern>com.yourcompany.shaded.apache</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build>

Agent模块:方法拦截处理器

package wxw.mengyuan; import net.bytebuddy.implementation.bind.annotation.*; import java.lang.reflect.Method; import java.util.concurrent.Callable; public class AgentInterceptor { @RuntimeType public static Object intercept(@Origin Method method, @SuperCall Callable<?> callable) throws Throwable { long start = System.currentTimeMillis(); try { return callable.call(); } finally { System.out.println("方法【" + method.getDeclaringClass().getName() + "." + method.getName() + "】执行耗时:" + (System.currentTimeMillis() - start) + "ms"); } } }

Agent模块:入口类

package wxw.mengyuan; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.utility.JavaModule; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain; public class DemoAgent { /** * JVM启动时加载 * @param agentArgs 参数 * @param inst 该对象可以操作一些类里面的方法 */ public static void premain(String agentArgs, Instrumentation inst) { System.out.println("静态加载:当前方法执行在main入口方法之前"); System.out.println("参数:" + agentArgs); // 创建转换器 AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() { @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) { return builder // 拦截哪些方法 // 仅此仅拦截 public 修饰符的方法 .method(ElementMatchers.isPublic()) // 声明拦截器 // 使用哪个类处理拦截逻辑 .intercept(MethodDelegation.to(AgentInterceptor.class)); } }; // 开始构建 new AgentBuilder.Default() // 拦截哪些类 // 此处仅拦截自身项目下、带有注解 @Controller、@RestController 的类 .type(ElementMatchers.nameStartsWith("wxw.mengyuan").and( ElementMatchers.isAnnotatedWith(ElementMatchers.named("org.springframework.web.bind.annotation.RestController")) .or(ElementMatchers.isAnnotatedWith(ElementMatchers.named("org.springframework.stereotype.Controller"))) )) // 设置转换器 .transform(transformer) // 开始安装 .installOn(inst); System.out.println("静态加载:加载完成"); } /** * JVM运行时动态加载 * @param agentArgs 参数 * @param inst 该对象可以操作一些类里面的方法 */ public static void agentmain(String agentArgs, Instrumentation inst) { System.out.println("JVM运行时动态加载"); } }

Spring MVC应用:Controller类

package wxw.mengyuan.banner; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.PostConstruct; @RestController @RequestMapping("/demo") public class DemoController { /** * 此方法会被拦截增强 */ @PostConstruct public void init() { System.out.println("Controller初始化完毕"); } /** * 此方法会被拦截增强 */ @RequestMapping("demoTest") public String demoTest() { print(); return "娃哈哈~"; } /** * 私有方法:此方法不会被拦截增强 */ private void print() { System.out.println("进入了Controller方法"); } }

Spring MVC应用:JVM参数

-javaagent:D:\Projects\DEMO\Demo-Agent\target\demo-agent-1.0.0.jar=key1=value1

Spring MVC应用:启动日志

Spring MVC应用:接口调用日志


动态加载示例

时机

在目标程序运行时动态附加

加载方式

通过 Attach API 加载

类加载状态

大部分应用类已加载,转换受限

能力

只能进行受限的字节码转换

重启要求

不需要重启 JVM

代码与运行示例

Agent模块:依赖坐标

<dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.17.8</version> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.17.8</version> </dependency>

Agent模块:pom.xml 插件配置

<build> <plugins> <!-- Java Agent插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.6.1</version> <executions> <execution> <!-- 插件在打包时才执行 --> <phase>package</phase> <!-- 插件执行时执行maven-shade-plugin的shade操作 --> <goals> <goal>shade</goal> </goals> <configuration> <!-- 不生成精简pom文件,保持完整的依赖树 --> <createDependencyReducedPom>false</createDependencyReducedPom> <transformers> <!-- 生成jar包时,添加Agent需要的MANIFEST.MF条目 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <!-- 入口配置 --> <manifestEntries> <!-- 静态加载Agent的入口类 --> <Premain-Class>wxw.mengyuan.DemoAgent</Premain-Class> <!-- 动态加载Agent的入口类 --> <Agent-Class>wxw.mengyuan.DemoAgent</Agent-Class> <!-- 允许重转换已加载类 --> <Can-Retransform-Classes>true</Can-Retransform-Classes> <!-- 允许重新定义类结构 --> <Can-Redefine-Classes>true</Can-Redefine-Classes> <!-- 设置native方法前缀 --> <Can-Set-Native-Method-Prefix>false</Can-Set-Native-Method-Prefix> </manifestEntries> </transformer> <!-- 合并所有依赖中 META-INF/services 目录下的文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <!-- 排除数字签名文件 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <!-- 重命名依赖避免冲突 --> <relocations> <relocation> <pattern>com.google</pattern> <shadedPattern>com.yourcompany.shaded.google</shadedPattern> </relocation> <relocation> <pattern>org.apache</pattern> <shadedPattern>com.yourcompany.shaded.apache</shadedPattern> </relocation> </relocations> </configuration> </execution> </executions> </plugin> </plugins> </build>

Agent模块:构造方法拦截处理器

package wxw.mengyuan; import net.bytebuddy.asm.Advice; import java.lang.reflect.Constructor; public class ConstructorAdvice { /** * 进入构造方法时调用 * @param constructor 构造方法 * @return 传给 @Advice.OnMethodExit 标注方法中的数据 */ @Advice.OnMethodEnter static long enter(@Advice.Origin Constructor<?> constructor) { System.out.println("进入构造方法: " + constructor.getDeclaringClass().getName()); return System.currentTimeMillis(); } /** * 退出构造方法时调用 * @param constructor 构造方法 * @param start @Advice.OnMethodEnter 标注方法的返回值 */ @Advice.OnMethodExit static void exit(@Advice.Origin Constructor<?> constructor, @Advice.Enter long start) { System.out.println("构造方法【" + constructor.getDeclaringClass().getName() + "】执行耗时:" + (System.currentTimeMillis() - start) + "ms"); } }

Agent模块:非构造方法拦截处理器

package wxw.mengyuan; import net.bytebuddy.asm.Advice; import net.bytebuddy.implementation.bytecode.assign.Assigner; import java.lang.reflect.Method; public class NotConstructorAdvice { /** * 进入方法时调用 * @param method 方法 * @return 传给 @Advice.OnMethodExit 标注方法中的数据 */ @Advice.OnMethodEnter static long enter(@Advice.Origin Method method) { System.out.println("进入方法: " + method.getDeclaringClass().getName() + "." + method.getName()); return System.currentTimeMillis(); } /** * 退出方法时调用 * @param method 方法 * @param start @Advice.OnMethodEnter 标注方法的返回值 * @param returnValue 方法返回结果 * @param throwable 异常 */ @Advice.OnMethodExit(onThrowable = Throwable.class) static void exit(@Advice.Origin Method method, @Advice.Enter long start, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object returnValue, @Advice.Thrown Throwable throwable) { String methodInfo = method.getDeclaringClass().getName() + "." + method.getName(); if (throwable != null) { System.err.println("方法【" + methodInfo + "】执行耗时:" + (System.currentTimeMillis() - start) + "ms,异常:" + throwable.getMessage()); } else { System.out.println("方法【" + methodInfo + "】执行耗时:" + (System.currentTimeMillis() - start) + "ms"); } } }

Agent模块:入口类

package wxw.mengyuan; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.matcher.ElementMatchers; import net.bytebuddy.utility.JavaModule; import java.lang.instrument.Instrumentation; import java.security.ProtectionDomain; public class DemoAgent { /** * JVM启动时加载 * @param agentArgs 参数 * @param inst 该对象可以操作一些类里面的方法 */ public static void premain(String agentArgs, Instrumentation inst) { System.out.println("静态加载:当前方法执行在main入口方法之前"); } /** * JVM运行时动态加载 * @param agentArgs 参数 * @param inst 该对象可以操作一些类里面的方法 */ public static void agentmain(String agentArgs, Instrumentation inst) { System.out.println("动态加载:JVM运行过程中加载"); System.out.println("参数:" + agentArgs); // 创建转换器 AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() { @Override public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) { return builder // 对构造方法的拦截处理 .visit(Advice.to(ConstructorAdvice.class).on(ElementMatchers.isConstructor())) // 对非构造方法的拦截处理 // 仅此仅拦截 public 修饰符的方法 .visit(Advice.to(NotConstructorAdvice.class).on(ElementMatchers.isPublic().and(ElementMatchers.not(ElementMatchers.isConstructor())))); } }; // 开始构建 new AgentBuilder.Default() .disableClassFormatChanges() .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) // 打印调试日志 .with(AgentBuilder.Listener.StreamWriting.toSystemOut().withErrorsOnly()) // 拦截哪些类 // 此处仅拦截自身项目下、带有注解 @Controller、@RestController 的类 .type(ElementMatchers.nameStartsWith("wxw.mengyuan").and( ElementMatchers.isAnnotatedWith(ElementMatchers.named("org.springframework.web.bind.annotation.RestController")) .or(ElementMatchers.isAnnotatedWith(ElementMatchers.named("org.springframework.stereotype.Controller"))) )) // 设置转换器 .transform(transformer) // 开始安装 .installOn(inst); System.out.println("动态加载:加载完成"); } }

Spring MVC应用:Controller类

package wxw.mengyuan.banner; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.PostConstruct; @RestController @RequestMapping("/demo") public class DemoController { /** * 此方法会被拦截增强 */ @PostConstruct public void init() { System.out.println("Controller初始化完毕"); } /** * 此方法会被拦截增强 */ @RequestMapping("demoTest") public String demoTest() { print(); return "娃哈哈~"; } /** * 私有方法:此方法不会被拦截增强 */ private void print() { System.out.println("进入了Controller方法"); } }

Spring MVC应用:启动日志

测试工程:依赖坐标

<dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy</artifactId> <version>1.17.8</version> </dependency> <dependency> <groupId>net.bytebuddy</groupId> <artifactId>byte-buddy-agent</artifactId> <version>1.17.8</version> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.18.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> <version>5.18.1</version> <scope>compile</scope> </dependency>

测试工程:测试类(编写后运行)

package com.mengyuan; import net.bytebuddy.agent.VirtualMachine; import java.io.IOException; public class DemoMain { public static void main(String[] args) { try { // 参数为目标JVM的PID VirtualMachine vm = VirtualMachine.ForHotSpot.attach("56900"); vm.loadAgent("D:\\Projects\\DEMO\\Demo-Agent\\target\\demo-agent-1.0.0.jar=key1=value1"); System.out.println("运行时动态加载成功"); } catch (IOException e) { throw new RuntimeException(e); } } }

Spring MVC应用:动态加载日志

Spring MVC应用:接口调用日志

学AI大模型的正确顺序,千万不要搞错了

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 1:20:37

GitHub 热榜项目 - 日榜(2026-01-26)

GitHub 热榜项目 - 日榜(2026-01-26) 生成于&#xff1a;2026-01-26 统计摘要 共发现热门项目&#xff1a; 9 个 榜单类型&#xff1a;日榜 本期热点趋势总结 本期GitHub热榜凸显AI应用开发的蓬勃创新&#xff0c;聚焦于高效能、低代码和跨模态技术。语音AI领域表现抢眼&a…

作者头像 李华
网站建设 2026/6/8 16:51:55

Java技术八股学习Day25

操作系统&#xff08;二&#xff09;内存管理&#xff08;1&#xff09;内存管理核心职责内存管理是操作系统的核心功能&#xff0c;主要负责内存分配与回收&#xff08;通过 malloc 申请、free 释放&#xff09;、地址转换&#xff08;虚拟地址转物理地址&#xff09;、内存扩…

作者头像 李华
网站建设 2026/5/18 12:01:57

有没有像HiPlot一样方便的科研数据可视化绘图网站或者软件?

在当今科研领域&#xff0c;数据可视化的重要性不言而喻。无论是学术研究还是工业应用&#xff0c;一张好的图表往往能够帮助我们更直观地理解复杂的数据关系&#xff0c;发现隐藏的规律。然而&#xff0c;传统的数据可视化工具往往需要较高的编程技能和大量的时间投入&#xf…

作者头像 李华
网站建设 2026/6/9 19:42:32

光伏VSG仿真Simulink

光伏vsg仿真simulink 咱们今天聊点硬核的——光伏电站并网时怎么用虚拟同步发电机&#xff08;VSG&#xff09;技术稳住电网。搞过新能源并网的都知道&#xff0c;光伏输出功率跟天气挂钩&#xff0c;动不动就给你整出个电压波动&#xff0c;这时候VSG就像个"戏精"&…

作者头像 李华
网站建设 2026/6/9 5:13:03

基于斑点鬣狗的LSSVM回归预测:PSO - LSSVM的探索

基于斑点鬣狗的LSSVM回归预测PSO-LSSVM 为了提高最小二乘支持向量机&#xff08;lssvm&#xff09;的回归预测准确率&#xff0c;对lssvm中的惩罚参数和核惩罚参数利用斑点猎狗算法进行优化。 Matlab 代码 在机器学习的领域中&#xff0c;提高预测模型的准确率一直是众多研究者…

作者头像 李华
网站建设 2026/6/10 1:00:24

20260126_215218_RAG(Retrieval-Augmented_Genera

RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09; 是大语言模型应用中的一项核心技术框架。简单来说&#xff0c;它的核心思想是&#xff1a;先检索&#xff0c;后生成。 为了让一个只会“凭空想象”的大模型变成一个能“引经据典”的专家…

作者头像 李华