核心思想
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
......
很熟悉吧,我们要插桩的这个对象就是 ComboPooledDataSource ,
如何很直观的展示出来的
- 实时获取ComboPooledDataSource的属性信息
- 简洁直观的展示相关属性信息
实现第一个,那就在ComboPooledDataSource构造函数后下手,将ComboPooledDataSource放到System Properties 中, 然后开启一个HTTP服务,对外提供服务访问即可。
编码实现
package com.artisan.agent.collect.c3p0;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.LoaderClassPath;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.net.InetSocketAddress;
import java.security.ProtectionDomain;
import java.util.concurrent.Executors;
/**
* @author 小工匠
* @version 1.0
* @description: C3P0插桩
* @date 2020/8/29 9:15
* @mark: show me the code , change the world
*/
public class C3P0Agent {
// 要插装的类
static String targetClass = "com.mchange.v2.c3p0.ComboPooledDataSource";
public static void premain(String args , Instrumentation instrumentation){
// 类转换器处理插桩逻辑
instrumentation.addTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
// 插桩后的对象
byte[] result = null;
// 条件判断
if (className != null && className.replace("/", ".").equals(targetClass)){
// 实例化pool , 将当前的ClassLoader设置到pool
ClassPool pool = new ClassPool();
pool.insertClassPath(new LoaderClassPath(loader));
try {
// 获取目标对象
CtClass ctl = pool.get(targetClass);
// 获取构造函数,插桩 将对象放入系统属性中
ctl.getConstructor("()V") //构造函数
.insertAfter("System.getProperties().put(\"c3p0Source$agent\", $0);"); // $0 this本身
// 转成class
result = ctl.toBytecode();
// 暴漏HTTP服务
new C3P0Agent().openHttpServer();
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
});
}
/**
* 对外提供Http 服务展示DataSource当前状态
* @throws IOException
*/
private void openHttpServer() throws IOException {
InetSocketAddress addr = new InetSocketAddress(7777);
HttpServer server = HttpServer.create(addr, 0);
// 设置上下文
server.createContext("/", new MyHttpHandler());
server.setExecutor(Executors.newCachedThreadPool());
server.start();
}
private class MyHttpHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
Headers responseHeaders = exchange.getResponseHeaders();
responseHeaders.set("Content-Type", "text/plain;charset=UTF-8");
exchange.sendResponseHeaders(200, 0);
OutputStream responseBody = exchange.getResponseBody();
// 输出c3p0状态
responseBody.write(C3P0Agent.this.getStatus().getBytes());
responseBody.flush();
responseBody.close();
}
}
public String getStatus() {
Object source2 = System.getProperties().get("c3p0Source$agent");
if (source2 == null) {
return "未初始任何c3p0数据源";
}
return source2.toString();
}
}
打包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>artisan-apm</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apm-agent</artifactId>
<dependencies>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.1-GA</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<manifestEntries>
<Project-name>${project.name}</Project-name>
<Project-version>${project.version}</Project-version>
<Boot-Class-Path>javassist-3.18.1-GA.jar</Boot-Class-Path>
<Premain-Class>com.artisan.agent.collect.c3p0.C3P0Agent</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>org.javassist:javassist</include>
</includes>
</artifactSet>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.artisan.agent.collect.c3p0.C3P0Agent</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
打包的时候,连同javassist也打包进去
配置验证
在启动的JVM参数中配置如下信息
-javaagent:D:\IdeaProjects\artisan-apm\apm-agent\target\apm-agent-1.0-SNAPSHOT.jar
然后,访问 http:// localhost:7777
本文标题:APM - 使用JavaAgent+Javassit 插桩C3P0
本文链接:https://blog.quwenai.cn/post/6771.html
版权声明:本文不使用任何协议授权,您可以任何形式自由转载或使用。












还没有评论,来说两句吧...