ngrok工具
ngrok 是一个反向代理,通过在公共的端点和本地运行的Web 服务器之间建立一个安全的通道。 ngrok 可捕获和分析所有通道上的流量,便于后期分析和重放。 反向代理在计算机网络中是代理服务器的一种。
相关科普文章:https://zhuanlan.zhihu.com/p/43628167 https://www.xncoding.com/2017/12/29/web/ngrok.html
kt-connect
https://github.com/alibaba/kt-connect
研发侧利器,本地连通 Kubernetes 集群内网
相关介绍文档 https://developer.aliyun.com/article/751321
spring xsd和dtd区别
可参考:https://blog.csdn.net/win7system/article/details/91553401
java agent
java agent本质上可以理解为一个插件,该插件就是一个精心提供的jar包,这个jar包通过JVMTI(JVM Tool Interface)完成加载,最终借助JPLISAgent(Java Programming Language Instrumentation Services Agent)完成对目标代码的修改。
可以在加载java文件之前做拦截把字节码做修改
可以在运行期将已经加载的类的字节码做变更
还有其他的一些小众的功能
- 获取所有已经被加载过的类
- 获取所有已经被初始化过了的类
- 获取某个对象的大小
- 将某个jar加入到bootstrapclasspath里作为高优先级被bootstrapClassloader加载
- 将某个jar加入到classpath里供AppClassloard去加载
- 设置某些native方法的前缀,主要在查找native方法的时候做规则匹配
通过java agent技术进行类的字节码修改最主要使用的就是Java Instrumentation API。下面将介绍如何使用Java Instrumentation API进行字节码修改。
1.实现java agent启动的方法
Java Agent支持目标JVM启动时加载,也支持在目标JVM运行时加载,这两种不同的加载模式会使用不同的入口函数,如果需要在目标JVM启动的同时加载Agent,那么可以选择实现下面的方法:
1 | [public static void premain(String agentArgs, Instrumentation inst); ] |
JVM将首先寻找[1],如果没有发现[1],再寻找[2]。如果希望在目标JVM运行时加载Agent,则需要实现下面的方法:
1 | [public static void agentmain(String agentArgs, Instrumentation inst); ] |
这两组方法的第一个参数AgentArgs是随同 “–javaagent”一起传入的程序参数,如果这个字符串代表了多个参数,就需要自己解析这些参数。inst是Instrumentation类型的对象,是JVM自动传入的,我们可以拿这个参数进行类增强等操作。
2. 指定Main-Class
Agent需要打包成一个jar包,在ManiFest属性中指定“Premain-Class”或者“Agent-Class”,且需根据需求定义Can-Redefine-Classes和Can-Retransform-Classes:
1 | Manifest-Version: 1.0 |
3.agent加载
- 启动时加载
- 启动参数增加-javaagent:[path],其中path为对应的agent的jar包路径
- 运行中加载
- 使用com.sun.tools.attach.VirtualMachine加载
1 | try { |
4. Instrument
instrument是JVM提供的一个可以修改已加载类的类库,专门为Java语言编写的插桩服务提供支持。它需要依赖JVMTI的Attach API机制实现。在JDK 1.6以前,instrument只能在JVM刚启动开始加载类时生效,而在JDK 1.6之后,instrument支持了在运行时对类定义的修改。要使用instrument的类修改功能,我们需要实现它提供的ClassFileTransformer接口,定义一个类文件转换器。接口中的transform()方法会在类文件被加载时调用,而在transform方法里,我们可以利用上文中的ASM或Javassist对传入的字节码进行改写或替换,生成新的字节码数组后返回。
首先定义类转换器
1 | public class TestTransformer implements ClassFileTransformer { |
类转换器定义完毕后,需要将定义好的类转换器添加到对应的instrumentation中,对于已经加载过的类使用retransformClasses对类进行重新加载:
1 | public class AgentDemo { |
从上图的代码可以看出,主方法实现了两个,分别为agentmain和premain,其中
premain
- 用于在启动时,类加载前定义类的TransFormer,在类加载的时候更新对应的类的字节码
agentmain
- 用于在运行时进行类的字节码的修改,步骤整体分为两步
- 注册类的TransFormer
- 调用retransformClasses函数进行类的重加载
参考文档
作者:kokov
链接:https://www.jianshu.com/p/d573456401eb
来源:简书