java log4j 热部署_Java 调式、热部署、JVM 背后的支持者 Java Agent
我们平时写 Java Agent 的机会确实不多,也可以说几乎用不着。但其实我们一直在用它,而且接触的机会非常多。下面这些技术都使用了 Java Agent 技术,看一下你就知道为什么了。
- 各个 Java IDE 的调试功能,例如 eclipse、IntelliJ ;
- 热部署功能,例如 JRebel、XRebel、 spring-loaded;
- 各种线上诊断工具,例如 Btrace、Greys,还有阿里的 Arthas;
- 各种性能分析工具,例如 Visual VM、JConsole 等;
Java Agent 直译过来叫做 Java 代理,还有另一种称呼叫做 Java 探针。首先说 Java Agent 是一个 jar 包,只不过这个 jar 包不能独立运行,它需要依附到我们的目标 JVM 进程中。我们来理解一下这两种叫法。
代理:比方说我们需要了解目标 JVM 的一些运行指标,我们可以通过 Java Agent 来实现,这样看来它就是一个代理的效果,我们最后拿到的指标是目标 JVM ,但是我们是通过 Java Agent 来获取的,对于目标 JVM 来说,它就像是一个代理;
探针:这个说法我感觉非常形象,JVM 一旦跑起来,对于外界来说,它就是一个黑盒。而 Java Agent 可以像一支针一样插到 JVM 内部,探到我们想要的东西,并且可以注入东西进去。
拿上面的几个我们平时会用到的技术举例子。拿 IDEA 调试器来说吧,当开启调试功能后,在 debugger 面板中可以看到当前上下文变量的结构和内容,还可以在 watches 面板中运行一些简单的代码,比如取值赋值等操作。还有 Btrace、Arthas 这些线上排查问题的工具,比方说有接口没有按预期的返回结果,但日志又没有错误,这时,我们只要清楚方法的所在包名、类名、方法名等,不用修改部署服务,就能查到调用的参数、返回值、异常等信息。
上面只是说到了探测的功能,而热部署功能那就不仅仅是探测这么简单了。热部署的意思就是说再不重启服务的情况下,保证最新的代码逻辑在服务生效。当我们修改某个类后,通过 Java Agent 的 instrument 机制,把之前的字节码替换为新代码所对应的字节码。
Java Agent 结构
Java Agent 最终以 jar 包的形式存在。主要包含两个部分,一部分是实现代码,一部分是配置文件。
配置文件放在 META-INF 目录下,文件名为 MANIFEST.MF 。包括以下配置项:
Manifest-Version: 版本号
Created-By: 创作者
Agent-Class: agentmain 方法所在类
Can-Redefine-Classes: 是否可以实现类的重定义
Can-Retransform-Classes: 是否可以实现字节码替换
Premain-Class: premain 方法所在类
入口类实现 agentmain 和 premain 两个方法即可,方法要实现什么功能就由你的需求决定了。
Java Agent 实现和使用
接下来就来实现一个简单的 Java Agent,基于 Java 1.8,主要实现两点简单的功能:
1、打印当前加载的所有类的名称;
2、监控一个特定的方法,在方法中动态插入简单的代码并获取方法返回值;
在方法中插入代码主要是用到了字节码修改技术,字节码修改技术主要有 javassist、ASM,已经 ASM 的高级封装可扩展 cglib,这个例子中用的是 javassist。所以需要引入相关的 maven 包。
实现入口类和功能逻辑
入口类上面也说了,要实现 agentmain 和 premain 两个方法。这两个方法的运行时机不一样。这要从 Java Agent 的使用方式来说了,Java Agent 有两种启动方式,一种是以 JVM 启动参数 -javaagent:xxx.jar 的形式随着 JVM 一起启动,这种情况下,会调用 premain方法,并且是在主进程的 main方法之前执行。另外一种是以 loadAgent 方法动态 attach 到目标 JVM 上,这种情况下,会执行 agentmain方法。
代码实现如下:
我们看到这两个方法都有参数 agentArgs 和 inst,其中 agentArgs 是我们启动 Java Agent 时带进来的参数,比如-javaagent:xxx.jar agentArgs。Instrumentation Java 开放出来的专门用于字节码修改和程序监控的实现。我们要实现的打印已加载类和修改字节码也就是基于它来实现的。其中 inst.getAllLoadedClasses()一个方法就实现了获取所以已加载类的功能。
inst.addTransformer方法则是实现字节码修改的关键,后面的参数就是实现字节码修改的实现类,代码如下:
以上代码的逻辑就是当碰到加载的类是 kite.attachapi.Person的时候,在其中的 test 方法开始时插入一条打印语句,打印内容是"动态插入的打印语句",在test方法结尾处,打印返回值,其中$_就是返回值,这是 javassist 里特定的标示符。
MANIFEST.MF 配置文件
在目录 resources/META-INF/ 下创建文件名为 MANIFEST.MF 的文件,在其中加入如下的配置内容:
配置打包所需的 pom 设置
最后 Java Agent 是以 jar 包的形式存在,所以最后一步就是将上面的内容打到一个 jar 包里。
在 pom 文件中加入以下配置
用的是 maven 的 maven-assembly-plugin 插件,注意其中要用 manifestFile 指定 MANIFEST.MF 所在路径,然后指定 jar-with-dependencies ,将依赖包打进去。
上面这是一种打包方式,需要单独的 MANIFEST.MF 配合,还有一种方式,不需要在项目中单独的添加 MANIFEST.MF 配置文件,完全在 pom 文件中配置上即可。
这种方式是将 MANIFEST.MF 的内容全部写作 pom 配置中,打包的时候就会自动将配置信息生成 MANIFEST.MF 配置文件打进包里。
运行打包命令
接下来就简单了,执行一条 maven 命令即可。
mvn assembly:assembly
最后打出来的 jar 包默认是以「项目名称-版本号-jar-with-dependencies.jar」这样的格式生成到 target 目录下。
运行打包好的 Java Agent
首先写一个简单的测试项目,用来作为目标 JVM,稍后会以两种方式将 Java Agent 挂到这个测试项目上。
以上只有一个简单的 main 方法,用 while 的方式保证线程不退出,并且在输入数字 1 的时候,调用 person.test()方法。
以下是 Person 类
以命令行的方式运行
因为项目是在 IDEA 里创建的,为了省事儿,我就直接在 IDEA 的 「Run/Debug Configurations」里加参数了。
-javaagent:/java-agent路径/lab-custom-agent-1.0-SNAPSHOT-jar-with-dependencies.jar
然后直接运行就可以看到效果了,会看到加载的类名称。然后输入数字键 "1",会看到字节码修改后的内容。
以动态 attach 的方式运行
测试之前先要把这个测试项目跑起来,并把之前的参数去掉。运行后,找到这个它的进程id,一般利用jps -l即可。
动态 attach 的方式是需要代码实现的,实现代码如下:
运行上面的 main 方法 并在测试程序中输入“1”,会得到上图同样的结果。
发现了没,我们到这里实现的简单的功能是不是和 BTrace 和 Arthas 有点像呢。我们拦截了指定的一个方法,并在这个方法里插入了代码而且拿到了返回结果。如果把方法名称变成可配置项,并且把返回结果保存到一个公共位置,例如一个内存数据库,是不是我们就可以像 Arthas 那样轻松的检测线上问题了呢。当然了,Arthas 要复杂的多,但原理是一样的。
sun.management.Agent 的实现
不知道你平时有没有用过 visualVM 或者 JConsole 之类的工具,其实,它们就是用了 management-agent.jar 这个Java Agent 来实现的。如果我们希望 Java 服务允许远程查看 JVM 信息,往往会配置上一下这些参数:
这些参数都是 management-agent.jar 定义的。
我们进到 management-agent.jar 包下,看到只有一个 MANIFEST.MF 配置文件,配置内容为:
可以看到入口 class 为 sun.management.Agent,进到这个类里面可以找到 agentmain 和 premain,并可以看到它们的逻辑。在这个类的开始,能看到我们前面对服务开启远程 JVM 监控需要开启的那些参数定义。
不要吝惜你的「关注」呦
java log4j 热部署_Java 调式、热部署、JVM 背后的支持者 Java Agent相关推荐
- ssm如何支持热部署_Java 调式、热部署、JVM 背后的支持者 Java Agent
我们平时写 Java Agent 的机会确实不多,也可以说几乎用不着.但其实我们一直在用它,而且接触的机会非常多.下面这些技术都使用了 Java Agent 技术,看一下你就知道为什么了. -各个 J ...
- java wrapper怎么运行_java wrapper方式部署项目
java项目部署的方式多种多样,目前springboot框架下都是自带tomcat等服务运行环境的,也可以直接将编译包后的jar包解压后运行起来,今天要介绍的是用wrapper的方式部署项目,这种方式 ...
- java 获取内存地址_Java 的多态在 JVM 里原来是这样的
多态 面向对象的编程语言里,「多态」是一个至关重要的概念.我们常说,面向对象的本质,是方法与数据的绑定.那对于一个拥有继承关系的类之间,方法的绑定,是终是子类「重写」父类的方法,通过父类的引用指向子类 ...
- java 部署_JAVA项目服务器部署
搜索jdk下载,然后进入JAVA官方网站jdk下载页,选择自己的对应的操作系统,点击下载 下载对应的版本: 2.安装JDK,这一步全默认选择一直点击下一步next就可以了(注意路径C盘). 3.安装完 ...
- java log4j 写日志_Java log4j同时写入文本日志和数据库日志
版权声明:转载原创文章请以超链接形式请注明原文章出处,尊重作者,尊重原创! 恰饭广告 Log4jUtil.java import org.apache.log4j.Logger; import org ...
- java dump分析工具_Java 性能分析工具 (2):Java 内置监控工具
引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...
- java失败javac成功_JAVA SE JDK-10安装、配置(解决java成功,javac失败问题)
本文是在win10环境下安装JDK-10 在linux环境下安装JDK-10请点击:CentOS 7 安装.配置JDK-10 1.下载JDK包 点击打开下载网站 点击图中的Accept License ...
- java中doloop语句_Java中的do-while循环——通过示例学习Java编程(11)
作者:CHAITANYA SINGH 来源:https://www.koofun.com/pro/kfpostsdetail?kfpostsid=22&cid=0 在上一篇教程中,我们讨论了w ...
- java 字符串 面试题_Java常用类String的面试题汇总(java面试题)
1.比较两个字符串时使用"=="还是equals()方法? 当然是equals方法."=="测试的是两个对象的引用是否相同,而equals()比较的是两个字符串 ...
- java long类型赋值_Java语言编程第22讲——如何理解“Java是强类型语言”
强类型语言,即Strongly Typed Language,从字面上理解,就是Java语言对类型要求很严格. Java语言对类型要求有哪些呢? 1.变量必须先声明类型,然后使用 例如: int i; ...
最新文章
- json数组 js html标签,js定义json对象数组 json 数组也是数组 //
- 什么是未定义的引用/未解决的外部符号错误,如何解决?
- 【PC工具】U盘SD卡测试工具,速度测试,坏块测试查找
- 安卓中bundle的使用
- [C++11]共享智能指针shared_ptr指定删除器
- MyEclipse的Debug功能最基本的操作
- 输入框设置只能输入数字
- html+css实现响应式布局入门
- 《信息熵,联合熵,条件熵,交叉熵,相对熵》
- 小操作_js调出outlook
- php openoffice,php实现openoffice转pdf的方法
- Globle Get 多线程下载系统
- 六轴陀螺仪简介及在智能车中的应用
- 阿里巴巴初创时的十八罗汉,离开阿里之后都有什么故事?
- 如何在vue中优雅的使用ocx控件:控件引用
- 2019年618提前引发“骚动”:苏宁要成为主场?!
- 电脑重启很久一直在转_电脑重启后鼠标一直在转圈怎么办
- 《惢客创业日记》2021.01.27-31(周三)顾耀东傻吗?
- 活动 | 旷视「智见AI」SpringCamp圆满结营 (附回放链接)
- 杰力科创手持小风扇芯片——DLTAP703SC
热门文章
- sersync+rsync多实例网站数据同步
- fir.im Weekly - 如何打造真正的工程师文化
- Python 画数学函数图像 matplotlib.pyplot
- QT创建和使用动态链接库
- idea 2019.2 svn 忽略文件/目录 .idea *.iml target log
- android阴影edittext,android – 将阴影效果添加到EditText字段
- 计算机与科学 研究生考试内容,计算机科学与技术考研考哪些科目 备考技巧有哪些...
- fastcopy会损坏硬盘_绚丽多彩 卓有不凡 三星移动固态硬盘T5金属红新品评测
- android实战技巧,实战技巧:Android异步指南
- cut 排序 linux,linux文本查看及处理工具wc, cut, sort, uniq和9道练习题