《Arthas系列三》Arthas的程序入口java agent,Java程序的后门
agent 是什么?
Java Agent 是 Java 虚拟机提供的一整套后门,通过这套后门可以对虚拟机方方面面进行监控与分析,甚至干预虚拟机的运行。直白点理解你可以控制你的程序,想做什么东西都可以。
agent 怎么用?
启动java agent 有两种方式:
一种是在程序启动的时候,启动agent,我们的本地调试就是通过这种方式。
一种是在程序启动之后,正常运行的时候,在自己想控制的时候attach上去,远程调试就是通过这种方式。 Attach 机制的核心组件是 Attach Listener,顾名思义,Attach Listener 是 JVM 内部的一个线程,这个线程的主要工作是监听和接收客户端进程通过 Attach 提供的通信机制发起的命令,你调试的时候看到过这个线程吗? 现在知道是怎么使用了吧。
可以看到调试的核心技术就是这个了,打开了大门,至于其他都是业务层面了。
agent 的技术
实现premain方法,在JVM启动前加载
实现agentmain方法,在JVM启动后attach加载
说太多也没啥用,直接来个例子吧。
创建2个maven项目, 一个是agent项目,一个是test项目
agent代码
我们看下源码,先看agent,因为这个需要注意的比较少
package com.pdool;
import java.lang.instrument.Instrumentation;
/**
* Hello world!
*/
public class App {
// 随程序启动的时候调用
public static void premain(String agentArgs, Instrumentation instrumentation) {
sayHello(agentArgs, instrumentation, "premain");
}
// attach的是调用
public static void agentmain(String agentArgs, Instrumentation instrumentation) {
sayHello(agentArgs, instrumentation, "agentMain");
}
public static void sayHello(String agentArgs, Instrumentation instrumentation, String methodName) {
System.out.println("from -----------" + methodName);
}
}
接着在pom.xml中增加一些打包的参数
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<!--自动添加META-INF/MANIFEST.MF -->
<manifest>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<!-- 这两个记得填写全路径 -->
<Premain-Class>com.pdool.App</Premain-Class>
<Agent-Class>com.pdool.App</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
这个打包的插件会自动创建MANIFEST.MF,并且修改,可以在打包完成后,看下是不是如自己的设置的 ,可以使用压缩软件打开哦,然后使用记事本查看
打包直接用maven的生命周期,package 命令就行,打包的路径就是target下面
接下来看下测试的代码
就是一个每隔2s运行一次的长须
package com.pdool;
/**
* Hello world!
*
*/
public class TestDemo
{
public static void main(String[] args) throws InterruptedException {
int index =0;
System.out.println("---- start ----");
while (true) {
Thread.sleep(2000);
System.out.println("Hello World! " + index++);
}
}
}
接下来先验证pre-main
运行上面的testDemo 修改运行参数,添加vm参数
记得把上面的路径改为你本地的路径 运行之后就可以看到
恭喜你,你的agent已经生效了
接下来验证agent-main
先把我们的TestDemo运行起来,然后使用jps 查看我们的pid
这里可以看到我们的pid 是9520,留着备用
启动agent代码
package com.pdool;
import com.sun.tools.attach.VirtualMachine;
import java.util.Scanner;
public class AttachTest {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
int pid = scanner.nextInt();
VirtualMachine virtualMachine = VirtualMachine.attach(String.valueOf(pid));
virtualMachine.loadAgent("E:\github\JavaAgentDemo\target\JavaAgentDemo-1.0-SNAPSHOT.jar");
Thread.sleep(10000L);
virtualMachine.detach();
}
}
如果你想运行上面的代码,会发现无法导包,是因为pom中需要配置tools.jar
<dependency>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
<version>1.8.0</version>
<scope>system</scope>
<systemPath>C:/Program Files/Java/jdk1.8.0_121/lib/tools.jar</systemPath>
</dependency>
这里面有几点需要注意: 1、包的id 是jdk.tools
2、本地路径要换成你机器的路径,同时不能使用\ 要用linux的/
3、scope 是是system
接下来启动AttackTest,然后输入上面的pid,转到TestDemo 就可以看到输出。 你就可以启动你的agent,这也是Arthas的使用方式。
Arthas 对agent 的使用
Arthas的使用基本上是上面的第二种,因为一般生产环境没有人会在服务启动的时候直接把Arthas启动起来,就像没有人会随身携带一个医生是一样的。 Arthas的使用将上面的直接合并了,在启动之后会列出所有的皮豆,然后直接选择,attach上去
总结
java agent 在平常的开发中使用不多,但是功能很强大
- 点赞
- 收藏
- 关注作者
评论(0)