Java Agent(java 探针)虽说在 jdk1.5 之后就有了,但是对于绝大多数的业务开发 javaer 来说,这个东西还是比较神奇和陌生的;虽说在实际的业务开发中,很少会涉及到 agent 开发,但是每个 java 开发都用过,比如使用 idea 写了个 HelloWorld.java,并运行一下, 仔细看控制台输出

image

本篇将作为 Java Agent 的入门篇,手把手教你开发一个统计方法耗时的 Java Agent

I. Java Agent 开发

首先明确我们的开发环境,选择 IDEA 作为编辑器,maven 进行包管理

1. 核心逻辑

创建一个新的项目(or 子 module),然后我们新建一个 SimpleAgent 类

public class SimpleAgent {    /**     * jvm 参数形式启动,运行此方法     *     * @param agentArgs     * @param inst     */    public static void premain(String agentArgs, Instrumentation inst) {        System.out.println("premain");    }    /**     * 动态 attach 方式启动,运行此方法     *     * @param agentArgs     * @param inst     */    public static void agentmain(String agentArgs, Instrumentation inst) {        System.out.println("agentmain");    }}

我们先忽略上面两个方法的具体玩法,先简单看一下这两个方法的区别,注释上也说了

  • jvm 参数形式: 调用 premain 方法
  • attach 方式: 调用 agentmain 方法

其中 jvm 方式,也就是说要使用这个 agent 的目标应用,在启动的时候,需要指定 jvm 参数 -javaagent:xxx.jar,当我们提供的 agent 属于基础必备服务时,可以用这种方式

当目标应用程序启动之后,并没有添加-javaagent加载我们的 agent,依然希望目标程序使用我们的 agent,这时候就可以使用 attach 方式来使用(后面会介绍具体的使用姿势),自然而然的会想到如果我们的 agent 用来 debug 定位问题,就可以用这种方式

2. 打包

上面一个简单 SimpleAgent 就把我们的 Agent 的核心功能写完了(就是这么简单),接下来需要打一个 Jar 包

通过 maven 插件,可以比较简单的输出一个合规的 java agent 包,有两种常见的使用姿势

a. pom 指定配置

在 pom.xml 文件中,添加如下配置,请注意一下manifestEntries标签内的参数

org.apache.maven.plugins            maven-assembly-plugin            jar-with-dependenciescom.git.hui.agent.SimpleAgent                        com.git.hui.agent.SimpleAgent                        truetrueattachedpackage

然后通过 mvn assembly:assembly 命令打包,在target目录下,可以看到一个后缀为jar-with-dependencies的 jar 包,就是我们的目标

b. MANIFEST.MF 配置文件

通过配置文件MANIFEST.MF,可能更加常见,这里也简单介绍下使用姿势

  • 在资源目录(Resources)下,新建目录META-INF
  • 在META-INF目录下,新建文件MANIFEST.MF

文件内容如下

Manifest-Version: 1.0Premain-Class: com.git.hui.agent.SimpleAgentAgent-Class: com.git.hui.agent.SimpleAgentCan-Redefine-Classes: trueCan-Retransform-Classes: true

请注意,最后的一个空行(如果我上面没有显示的话,多半是 markdown 渲染有问题),不能少,在 idea 中,删除最后一行时,会有错误提醒

image

然后我们的pom.xml配置,需要作出对应的修改

org.apache.maven.plugins          maven-assembly-plugin          jar-with-dependencies                      src/main/resources/META-INF/MANIFEST.MF                  attachedpackage

同样通过mvn assembly:assembly命令打包

II. Agent 使用

agent 有了,接下来就是需要测试一下使用 agent 的使用了,上面提出了两种方式,我们下面分别进行说明

1. jvm 参数

首先新建一个 demo 项目,写一个简单的测试类

public class BaseMain {    public int print(int i) {        System.out.println("i: " + i);        return i + 2;    }    public void run() {        int i = 1;        while (true) {            i = print(i);            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) throws InterruptedException {        BaseMain main = new BaseMain();        main.run();        Thread.sleep(1000 * 60 * 60);    }}

测试类中,有一个死循环,各 1s 调用一下 print 方法,IDEA 测试时,可以直接在配置类,添加 jvm 参数,如下

image

请注意上面红框的内容为上一节打包的 agent 绝对地址: -javaagent:/Users/..../target/java-agent-1.0-SNAPSHOT-jar-with-dependencies.jar

执行 main 方法之后,会看到控制台输出

image

请注意上面的premain, 这个就是我们上面的SimpleAgent中的premain方法输出,且只输出了一次

2. attach 方式

在使用 attach 方式时,可以简单的理解为要将我们的 agent 注入到目标的应用程序中,所以我们需要自己起一个程序来完成这件事情

public class AttachMain {    public static void main(String[] args)            throws IOException, AgentLoadException, AgentInitializationException, AttachNotSupportedException {        // attach方法参数为目标应用程序的进程号        VirtualMachine vm = VirtualMachine.attach("36633");        // 请用你自己的agent绝对地址,替换这个        vm.loadAgent("/Users/......./target/java-agent-1.0-SNAPSHOT-jar-with-dependencies.jar");    }}

上面的逻辑比较简单,首先通过jps -l获取目标应用的进程号

image

当上面的 main 方法执行完毕之后,控制台会输出类似下面的两行日志,可以简单的理解为我连上目标应用,并丢了一个 agent,然后挥一挥衣袖不带走任何云彩的离开了

Connected to the target VM, address: '127.0.0.1:63710', transport: 'socket'Disconnected from the target VM, address: '127.0.0.1:63710', transport: 'socket'

接下来再看一下上面的 BaseMain 的输出,中间夹着一行agentmain, 就表明 agent 被成功注入进去了

image

3. 小结

本文介绍了 maven + idea 环境下,手把手教你开发一个 hello world 版 JavaAgent 并打包的全过程

两个方法

方法说明使用姿势premain()agent 以 jvm 方式加载时调用,即目标应用在启动时,指定了 agent-javaagent:xxx.jaragentmain()agent 以 attach 方式运行时调用,目标应用程序正常工作时使用VirtualMachine.attach(pid)来指定目标进程号
vm.loadAgent("...jar")加载 agent

两种打包姿势

打包为可用的 java agent 时,需要注意配置参数,上面提供了两种方式,一个是直接在pom.xml中指定配置

com.git.hui.agent.SimpleAgent    com.git.hui.agent.SimpleAgent    truetrue

另外一个是在配置文件 META-INF/MANIFEST.MF 中写好(需要注意最后一个空行不可或缺)

Manifest-Version: 1.0Premain-Class: com.git.hui.agent.SimpleAgentAgent-Class: com.git.hui.agent.SimpleAgentCan-Redefine-Classes: trueCan-Retransform-Classes: true

当然本篇内容看完之后,会发现对 java agent 的实际开发还是不太清楚,难道 agent 就是在前面输出一行hello world就完事了么,这和想象中的完全不一样啊

下一篇博文将手把手教你实现一个方法统计耗时的 java agent 包,将详细说明利用接口Instrumentation来实现字节码修改,从而是实现功能增强

II. 其他

0. 源码

  • https://github.com/liuyueyi/java-agent

idea git 过滤target_IDEA + maven 零基础构建 java agent 项目相关推荐

  1. java agent 开发_IDEA + maven 零基础构建 java agent 项目

    Java Agent(java 探针)虽说在 jdk1.5 之后就有了,但是对于绝大多数的业务开发 javaer 来说,这个东西还是比较神奇和陌生的:虽说在实际的业务开发中,很少会涉及到 agent ...

  2. 零基础学怎么学Java_零基础学java难么?怎么自学?

    在计算机发展迅速的今天,越来越多的人去学习编程,其中Java就是大家热衷的语言之一.这时候就有人问,零基础学java难么?下面小编将回答这一问题并给出学习路线. 小编想说,这个实际上要看个人能力以及前 ...

  3. java基础知识点_零基础学习Java语言,各个阶段需要掌握的知识点

    随社会的脚步的不断发展,Java技术在不断的与时俱进,这也是Java一直长盛不衰的原因之一.Java技术的学习,永远没有早晚之分,技不压身,对于21世纪的我们80后,90后,甚至00后,尤其适用! 那 ...

  4. myeclipse java maven web 项目结构,Myeclipse 10 Maven 构建 Java Web 项目

    下载 Maven http://maven.apache.org/download.cgi,解压到任意非C盘位置,比如:D:\Java\apache-maven-3.1.0 打开 Myeclipse ...

  5. 零基础学Java需知:Java小白入门解疑大全

    Java行业在互联网发展迅速的今天是一日比一日发展的好,Java语言已经成为世界上应用较广泛的编程语言.学Java已经成为编程语言中的潮流,越来越多的人有意向到Java行业中发展. 其实,零基础学习J ...

  6. 零基础自学java的难处_零基础自学Java 在学习中要注意哪些问题

    如果是零基础自学Java编程,在学习过程中有很多要注意的问题,想要学好学精必然是件难事,并且可能会走弯路浪费很多时间,短时间内是不可能学成参加工作的,想要成为专业的Java程序员并不容易,技术过硬尤为 ...

  7. 零基础写Java知乎爬虫之进阶篇

    转载自 零基础写Java知乎爬虫之进阶篇 前面几篇文章,我们都是简单的实现了java爬虫抓取内容的问题,那么如果遇到复杂情况,我们还能继续那么做吗?答案当然是否定的,之前的仅仅是入门篇,都是些基础知识 ...

  8. 零基础学JAVA怎么学?

    spring cloud分布式事务从入门到精通 (如下载连接失效,请私信我) 百度云下载链接:https://pan.baidu.com/s/1EtYyj7MEBqIGSYg2ljBFyg 提取码:n ...

  9. 视频教程-由浅入深Java零基础入门-Java

    由浅入深Java零基础入门 负责过多个软件项目的研发.设计和管理工作,拥有项目管理师认证.项目监理师中级认证.出版过的图书有<微信小程序开发图解案例教程><Axure RP8原型设计 ...

最新文章

  1. python opencv imread()函数,关于:灰度图(二维数组图),彩色图(三维数组图)
  2. Python学习:Python简介
  3. xshell上vim小键盘无法使用的解决方法
  4. python-数据容器-有序容器与无序容器
  5. arguments的理解
  6. 利用PlayerPrefs存储数据
  7. web操作日志丢失_日志异步落库,你了解不
  8. 如何下载安全绿色的代理IP软件
  9. 数据库练习题归纳整理
  10. 传销三级的认定标准_应为传销案件中“劳务性工作人员”争取“不起诉”—传销犯罪辩护与研究(四十五)...
  11. Nitrux 图标主题与 Faenza 一样的设计 – 漂亮
  12. 聊天室——MYSQL建表
  13. s3c2440存储控制器详解
  14. 微信小游戏世界排行榜的绘制
  15. mysql硬盘最长活动时间100%_win10磁盘活动时间100%,小编告诉你解决方法
  16. 如何去爱一个人[转]
  17. CS231n系列之 Lecture1:Introduction
  18. 【UNI-APP】开发微信公众号(H5)JSSDK调式
  19. scrapy 抓取拉钩 ajax
  20. 调用百度地图API出现 error inflating class com.baidu.mapapi.map.mapview

热门文章

  1. 1230: 最小花费(spfa)
  2. 新手必看 | RVB2601开发板快速上手指南
  3. 相机参数设置程序_自定义拍摄模式怎么设置?教你学会相机设置。
  4. 天刀手游制作人亲笔详解制作思路
  5. 金铲铲之战高峰期1万人排队,LOL手游如果公测会怎样?
  6. Python编程专属骚技巧2
  7. net use 命令集合详解
  8. 63. Unique Paths II 动态规划
  9. `MediaDevices.getUserMedia` `undefined` 的问题
  10. 一封电子邮件的发送和接收的主要步骤