Java Agent实现无侵入监控
Java Agent允许在JVM层面拦截和修改字节码,实现无侵入的监控,主要思路是通过字节码增强技术在方法执行前后插入监控代码。

核心实现方案
// 1. 创建Agent入口类
public class MonitorAgent {
// premain方式 - 启动时加载
public static void premain(String args, Instrumentation inst) {
System.out.println("Monitor Agent premain called");
inst.addTransformer(new MethodMonitorTransformer(), true);
}
// agentmain方式 - 运行时加载
public static void agentmain(String args, Instrumentation inst) {
System.out.println("Monitor Agent agentmain called");
inst.addTransformer(new MethodMonitorTransformer(), true);
}
}
// 2. 实现ClassFileTransformer
public class MethodMonitorTransformer implements ClassFileTransformer {
private static final Set<String> MONITORED_PACKAGES = new HashSet<>();
static {
MONITORED_PACKAGES.add("com/example/service");
MONITORED_PACKAGES.add("com/example/controller");
}
@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
// 只监控指定包下的类
if (!shouldMonitor(className)) {
return null;
}
try {
return enhanceClass(className, classfileBuffer);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private boolean shouldMonitor(String className) {
return MONITORED_PACKAGES.stream()
.anyMatch(pkg -> className != null && className.startsWith(pkg));
}
private byte[] enhanceClass(String className, byte[] classfileBuffer) {
// 使用ASM进行字节码增强
ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = new MonitorClassVisitor(cw, className);
cr.accept(cv, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
}
}
ASM字节码增强实现
// 3. 方法级别的监控增强
public class MonitorMethodVisitor extends MethodVisitor {
private final String className;
private final String methodName;
private final String methodDesc;
public MonitorMethodVisitor(MethodVisitor mv, String className,
String methodName, String methodDesc) {
super(Opcodes.ASM7, mv);
this.className = className;
this.methodName = methodName;
this.methodDesc = methodDesc;
}
@Override
public void visitCode() {
// 方法开始前插入监控代码
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/example/monitor/MonitorCollector",
"start",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
false);
super.visitCode();
}
@Override
public void visitInsn(int opcode) {
// 在return指令前插入监控代码
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
|| opcode == Opcodes.ATHROW) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/example/monitor/MonitorCollector",
"end",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
false);
}
super.visitInsn(opcode);
}
}
// 4. 监控数据收集器
public class MonitorCollector {
private static final Map<String, MethodMetrics> metricsMap = new ConcurrentHashMap<>();
private static final ThreadLocal<Long> startTime = new ThreadLocal<>();
public static void start(String className, String methodName, String desc) {
startTime.set(System.currentTimeMillis());
}
public static void end(String className, String methodName, String desc) {
Long start = startTime.get();
if (start == null) return;
long duration = System.currentTimeMillis() - start;
String key = className + "#" + methodName;
metricsMap.compute(key, (k, v) -> {
if (v == null) {
return new MethodMetrics(duration, 1);
}
v.addDuration(duration);
v.incrementCount();
return v;
});
// 发送到监控系统
reportToMonitorSystem(className, methodName, duration);
}
// 获取监控数据
public static Map<String, MethodMetrics> getMetrics() {
return new HashMap<>(metricsMap);
}
}
META-INF配置
在META-INF/MANIFEST.MF中配置:
Manifest-Version: 1.0 Premain-Class: com.example.monitor.MonitorAgent Agent-Class: com.example.monitor.MonitorAgent Can-Retransform-Classes: true Can-Redefine-Classes: true
使用方式
# 启动时加载
java -javaagent:monitor-agent.jar -jar application.jar
# 运行时加载(需要Attach API)
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent("monitor-agent.jar");
vm.detach();
高级功能扩展
// 5. 性能监控增强 - 统计P99延迟
public class PercentileMetrics {
private final ConcurrentSkipListMap<Long, Integer> latencyMap = new ConcurrentSkipListMap<>();
public long getLatencyAtPercentile(double percentile) {
long total = getTotalCount();
long target = (long) (total * percentile / 100);
long cumulative = 0;
for (Map.Entry<Long, Integer> entry : latencyMap.entrySet()) {
cumulative += entry.getValue();
if (cumulative >= target) {
return entry.getKey();
}
}
return 0;
}
}
// 6. 异常监控
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExceptionMonitor {
Class<? extends Throwable>[] value() default {Exception.class};
}
// 增强时检查注解
public class ExceptionMonitorAdvisor {
public static void addExceptionMonitoring(ClassNode cn, MethodNode mn) {
if (mn.visibleAnnotations != null) {
for (AnnotationNode an : mn.visibleAnnotations) {
if (an.desc.contains("ExceptionMonitor")) {
// 在方法开始和异常处理中添加监控
}
}
}
}
}
最佳实践建议
-
性能优化:
- 使用
COMPUTE_MAXS而非COMPUTE_FRAMES减少计算开销 - 在
transform方法中尽早过滤不需要增强的类 - 使用ThreadLocal减少锁竞争
- 使用
-
稳定性保障:
- 添加增强失败的回退机制
- 限制最大重试次数防止递归
- 监控Agent本身的资源消耗
-
安全考虑:
- 对增强的类进行白名单过滤
- 避免增强核心JDK类
- 提供安全降级机制
这种方案可以做到业务代码零侵入,并且支持动态加载和卸载,非常适合生产环境的监控需求。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播