Spring Cloud 下使用Javassist 在类被加载之前修改字节码 Spring Cloud 项目中,很多功能都是用 aop去实现的,或者直接使用Java Agent。...在两者都不能使用的情况下,我们可以考虑使用Javassist 直接操作字节码来实现。...我们需要使用Spring 的一个扩展点 ApplicationContextInitializer,在类被加载之前修改字节码,注意在Spring Cloud 环境下,一般存在父子容器,此扩展点被执行两次...; import javassist.CtClass; import javassist.CtMethod; import javassist.CtNewMethod; import java.util.Random..." + " throw ex;\n" + " }\n" + " return result;\n" + " }"); randomStringUtilsClass.toClass();//加载修改后的类
1、前言 在 Java Agent 开发中,动态字节码增强是一项核心技术,而 Javassist 是一个高效且易用的字节码操作库。...UserEntity.class内容: 控制台输出: 3.3、 修改已有类的方法 已有CatEntity.java类,通过javassist方法在sayHello方法前后,追加两个方法。...我在实验的时候,刚开始的是: public String sayHello(){ return "cat say hello:miao~"; } 在Javassist中修改方式为...: 4、原理机制 通过前面的示例代码可以看到,通过Javassist提供的一些api可以很顺利的对字节码进行操作,按需实现部分动态的修改。...生成 Class 和加载过程 修改完成的 CtClass 对象,通过 toClass 方法生成最终的 Java Class,这个过程基于 JVM 的动态进入加载机制,保证修改应用立即生效。
String getValue(String key) { return key; } } 2.2 增强 如何在不修改代码的前提下, 增加一段简单逻辑: 在返回结果前, 将参数打印出来...在方法体中插入增强语句 整个流程虽然非常简单, 但合理利用javassist API会完成更多功能. 三....在Tomcat等Web服务器运行时, 服务器会使用多个类加载器作为系统类加载器, 这可能导致ClassPool可能无法找到用户的类....Class clazz = ctClass.toClass(); // 类的字节码文件 ClassFile classFile = ctClass.getClassFile(); // 编译成字节码文件, 使用当前线程上下文类加载器加载类...ctMethod.insertBefore(""); // 在方法体后插入代码块 ctMethod.insertAfter(""); // 在某行 字节码 后插入代码块 ctMethod.insertAt
上节说了javaagent和javassist,其实javassist也是基于ASM实现的。...pom中添加javassist的jar包 org.javassist javassist<...注意代码 加入insertBefore中的bgin 和 insertAfter 的 end 通过end-begin 但是后台报错了 ?...在实际开发中不用修改原有的方法,而是会新写一个方法,在新方法进行出来,调用要插桩的方法。新方法的参数和要插桩的保持一致,包括注解,参数。其实有点类似动态代理。...具体如何实现,后面会说 PS:还需要结合之前文章111节里面的测试类,了解如何完成插桩和埋点。
Javassist是可以动态编辑Java字节码的类库。它可以在Java程序运行时定义一个新的类,并加载到JVM中;还可以在JVM加载时修改一个类文件。...动态生成类 Javassist可以在运行时动态地生成新的类,这个特性在一些框架中被广泛使用。...Javassist 的 API 与 Java 反射 API 比较相似,Java 类包含的字段、方法在 Javassist 中分别对应 CtField 和 CtMethod,通过 CtClass 对象就可以给类新增字段...insertBefore、insertAfter:在方法开始和结束插入语句。...在 Javassist 中访问方法参数使用 0 1 ...
AOP的实现一般使用了动态代理和字节码修改,本文介绍使用javassist实现类的创建和修改 添加依赖 org.javassist javassist 3.28.0-GA 使用字节码创建一个类 初始化...//修改: 在greeting之前插入逻辑 greetingMethod.insertBefore("System.out.println(\"before greeting~\");"); //...修改: 在greeting之前插入逻辑 greetingMethod.insertAfter("System.out.println(\"after greeting~\");"); //输出到类(...attempted duplicate class definition for name: "XXX" 因为对应的类信息已经加载,就不能修改了,否则就是重复定义 参考 Getting Started
Hello World 一起看个示例, 了解下agentmain是如何在运行时, 动态增强的....我们的目标是在不重启的情况下, 打印出abc()方法的运行时间. 2.1 Agentmain类 agentmain类中的参数会传入类全名和方法名, 并通过TimingTransformer类增加方法功能...两者的非本质功能的区别如下: 1. premain需要通过命令行使用外部代理jar包, 即-javaagent:代理jar包路径;agentmain则可以通过attach机制直接附着到目标VM中加载代理..., 也就是使用agentmain方式下, 操作attach的程序和被代理的程序可以是完全不同的两个程序. 2. premain方式回调到ClassFileTransformer中的类是虚拟机加载的所有类..., 这个是由于代理加载的顺序比较靠前决定的, 在开发者逻辑看来就是: 所有类首次加载并且进入程序main()方法之前, premain方法会被激活, 然后所有被加载的类都会执行ClassFileTransformer
本文将深入探讨Java Instrumentation的基础知识,并通过具体的代码示例来展示如何使用-javaagent选项以及premain和agentmain方法来实现一些实用的功能。...这可以通过Attach机制或者通过在启动时使用-javaagent参数同时指定agentmain类来实现。...如何Attach到远程JVM 要Attach到一个本地或远程的JVM,你需要使用jattach工具(从JDK 7开始包含在内)或者使用sun.tools.attach包中的API。...} } 通过Attach API动态加载agent 除了使用jattach命令行工具之外,你也可以编写代码来使用java.lang.management包中的RuntimeMXBean来Attach...此外,在生产环境中使用Attach功能时,应该小心处理权限和安全性问题。 以上就是关于如何使用agentmain方法结合Attach机制来动态加载Java agent的基本信息。
Api,可以让我们动态修改已加载或者未加载的类,包括类的属性和方法。...Java Agent 支持两种加载方式对java程序进行动态修改,分别为: 1. premain 方法,在启动时进行加载 。 2. agentmain 方法,在启动后进行加载 。...因此主要学习如何将一个agent加载进jvm里、学习agent在被加载后需要实施的行为(将恶意代码动态写进类里)。...redefineClasses 除了用自定义Transformer对目标类进行重新拦截加载,还可以使用redefineClasses直接对已经修改的字节码文件进行重新定义。...具体的解决方法在0x01-1点和0x03点都有提到:分别是提前将一个tools.jar包给打包进项目、利用ClassLoader加载目标机器jdk环境library中的tools.jar。
一、前言 字节码编程插桩这种技术常与 Javaagent 技术结合用在系统的非入侵监控中,这样就可以替代在方法中进行硬编码操作。...再通过后期的完善将监控信息展示到界面,实时报警。既提升了系统的监控质量,也方便了研发排查并定位问题。 好!那么接下来我们开始一步步使用 javassist 进行字节码插桩,已达到我们的监控效果。...并通过 insertBefore 插入到方法内容的开始处。...如果是实际的业务场景中,就可以通过这样的方法使用 MQ 将监控信息发送给服务端记录起来并做展示。...再通过在 catch 中调用外部方法,将异常信息输出。 同时有一个点需要注意,$e,用于获取抛出异常的内容。
修改配置文件并打包 配置文件:配置文件名为MANIFEST.MF,需放在META-INF文件夹下或者在maven中配置。 Premain-Class:表示实现premain方法的类。...Java Agent的加载 Java Agent的加载分为静态加载和动态加载。 静态加载 在应用程序启动时加载Java代理称为静态加载,静态加载在任何代码执行之前在启动时修改字节码。...-Xbootclasspath/a:D:\javassist-3.28.0-GA.jar是引用javassist包,当然也可以通过maven引入到项目中 启动MainTest进行测试 控制台打印结果:...静态加载和动态加载的区别 从上面的例子中可以发现静态加载是需要和被代理的程序一起启动,需要在启动的时候通过-javaagent参数指定静态加载的jar包,被代理的程序是“知道”自己被代理的。...总结 本篇文章我们分别使用Java Agent的静态加载和动态加载成功的对字节码进行了修改、追踪,并完成了一个打印方法耗时的简单示例。
❞ 一、前言 字节码编程插桩这种技术常与 Javaagent 技术结合用在系统的非入侵监控中,这样就可以替代在方法中进行硬编码操作。...再通过后期的完善将监控信息展示到界面,实时报警。既提升了系统的监控质量,也方便了研发排查并定位问题。 好!那么接下来我们开始一步步使用 javassist 进行字节码插桩,已达到我们的监控效果。...并通过 insertBefore 插入到方法内容的开始处。...如果是实际的业务场景中,就可以通过这样的方法使用 MQ 将监控信息发送给服务端记录起来并做展示。...再通过在 catch 中调用外部方法,将异常信息输出。 同时有一个点需要注意,$e,用于获取抛出异常的内容。
不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解;•javassist:一个开源的分析、编辑和创建Java...不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。...它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。...在实现成本上Javassist和反射都很低,而ASM由于直接操作字节码,相比Javassist源码级别的api实现成本高很多。几个方法有自己的应用场景,比如Kryo使用的是ASM,追求性能的最大化。...,比如ASM/byte-buddy/Java动态代理;另一种是使用Java编码方式创建新类或者修改现有类,比如javassist。
使用这种技术,几乎可以通过在已经部署的Java应用程序的字节码级别(JVM在运行时对其进行解释)上操作而对其进行任何更改,而无需修改应用程序的源代码(因为后者意味着需要重新编译、重新组装和重新部署应用程序...在实际开发中,这种详细输出应该禁用,或使用具有相应日志级别/重要性的应用服务器日志框架实现。...中,该agent通过agent加载来演示instrumentation; Java agent loader应用程序位于包vadim.demo.jvm.agent.loader中,用于演示从外部应用程序连接运行中的...AspectJ (The AspectJ Project) 在本博客的后面的示例中,我将在修改底层字节码的必要性和抽象之间作一个折衷,使用Javassist库 让我们增强演示程序的基本逻辑并对其instrument...在调用System.output.println()之前,我们将另一个值的赋值注入到使用的变量中,这样控制台输出的值就与从程序主类传递的值不同; 也可以通过引入所谓的表达式编辑器实现类改变已经存在的字节码
Class loader 类加载 如果必须修改的类是预先知道的,最简单的修改类的方式可能是以下这些: 1.通过调用ClassPool.get()获取一个CtClass对象。...2.修改它,并且 3.调用CtClass对象的writeFile()或者toBytecode()方法获得修改后的class文件 如果类是否被修改是在加载时确定的,用户必须让javassist与类加载器协作...javassist可以与类加载器一起使用,以便在加载时修改字节码。 用户可以使用自定义版本的类加载器,也可以使用javassist提供的类加载器。...类的CtClass修改其say方法,在方法体前面增加一行输出语句; 然后,通过CtClass的toClass方法请求当前线程(Javassist3ClassLoaderTest类所在的线程)去加载Javassist3ClassLoader...例如,javassist.Loader可用于使用javassist修改的指定的类: ClassPool pool = ClassPool.getDefault(); // 使用ClassPool创建Loader
因为我在开发一个框架的时候需要用到。 我开发的这个框架,有一个注解,当用户输入变量名,类名的时候,我这个框架可以为其自动生成一个对象,并加载到内存中供以后使用。 这个小功能可费尽心机。...它可以在Java程序运行时定义一个新的类,并加载到JVM中;还可以在JVM加载时修改一个类文件。Javassist使用户不必关心字节码相关的规范也是可以编辑类文件的。...CtClass中的CtField和CtMethod分别对应Java中的字段和方法。通过CtClass对象即可对类新增字段和修改方法等操作了。 ?...—— —— |a|1| |b|2| |c|3| —— —— 那么我们获取变量时就不能使用原始的名字了,在Javassist中访问方法中的参数使用的是$1,...我们以计算n的斐波拉契数列为例,来演示一下如何使用。
在上一期讲解java的动态性的时候,我们主要提到了java中的反射机制,可以在java代码运行的时候,改变类的结构,属性等信息,而这一节我们通过另一种实现方式来讲解java的动态性,主要就是java的字节码操作...一、了解一下字节码: 1、背景 在我们日常编程时,我们在IDE中编写好源代码之后,点击“run”,程序直接就运行了。但是点击“run”按钮之后,计算机是如何操作的呢?...; } } tips: (1)由上面的代码也可以看出使用javassist操作字节码的方式:首先获取一个类池“ClassPool”,通过类池,我们创建编译过程中的新类“CtClass”,...但是在方法二中,我们仅仅指定了两个形参的类型,而并没有给定形参名称,所以在使用返回值的时候,我们使用的是“return $1+$2”,其中“$1”和“$2”分别代表第一个和第二个形参。...我们为了修改该类的信息,首先获取cc的“SayHello”方法,然后我们分别使用方法“insertBefore”和方法“insertAfter”,在这个方法的前面分别插入相应的代码。
图16 字节码增强技术 2.1 ASM 对于需要手动操纵字节码的需求,可以使用ASM,它可以直接生成.class字节码文件,也可以在类被加载入JVM之前动态修改类行为(如下图17所示)。...这期间并不涉及到JVM运行时对类的重加载,而是在第一个Main方法中,通过ASM对已编译类的字节码进行替换,在第二个Main方法中,直接使用已替换好的新类信息。...另外在Javassist的实现中,我们也只加载了一次Base类,也不涉及到运行时重加载类。 如果我们在一个JVM中,先加载了一个类,然后又对其进行字节码增强并重新加载会发生什么呢?...TestTransformer做了Base类的字节码替换(通过javassist),并完成了类的重新加载。...图23 运行时重载入类的效果 3.4 使用场景 至此,字节码增强技术的可使用范围就不再局限于JVM加载类前了。通过上述几个类库,我们可以在运行时对JVM中的类进行修改并重载了。
在今年的敏捷团队建设中,我通过Suite执行器实现了一键自动化单元测试。Juint除了Suite执行器还有哪些执行器呢?由此我的Runner探索之旅开始了!...2.修改后的字节码如何注入运行时JVM中呢? 欲攻善其事,必先利其器,所以下面我们围绕着这两个问题进行展开,当然,对这方面知识已经有所掌握的同学可忽略。...3.1 字节码修改 字节码修改成熟的框架已经很多了,诸如:ASM、javassist、bytebuddy、bytekit,下面我们用这几个字节码修改框架实现一个相同的功能,来对比下这几个框架使用上的区别...),第12行遍历插件加载器加载插件,插件加载逻辑其实和service一样,使用的都是AddonLoader中的load方法。...,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将 5.1 多线程traceId丢失问题 pfinder目前已经将traceId放到了MDC中,我们通过在日志配置文件中添加
领取专属 10元无门槛券
手把手带您无忧上云