当前位置:网站首页>基于字节码的统一异常上报实践
基于字节码的统一异常上报实践
2022-06-29 11:06:00 【InfoQ】
基于字节码的统一异常上报实践
一、前言
二、异常介绍
2.1 认识异常
- 哪里发生异常?
- 谁来处理异常?
- 如何处理异常?
2.2 Java异常的分类

2.3 异常的处理流程

2.4 异常抛出与捕获的原则
- 非必要不使用异常
- 使用描述性消息抛出异常
- 力所能及的异常一定要处理
- 异常忽略要有理有据
2.5 认识try/catch/finally
- 代码执行流程未进入try代码块。
- 代码在try代码块中发生死循环、死锁等状态。
- 在try代码块中执行了System.exit()操作。
三、异常处理
3.1 处理异常的最佳实践
- 当需要向上抛出异常的时候,需根据当前业务场景定义具有业务含义的异常,优先使用行业内定义的异常或者团队内部定义好的。例如在使用dubbo进行远程服务调用超时的时候会抛出DubboTimeoutException,而不是直接把RuntimeException抛出。
- 请勿在finally代码块中使用return语句,避免返回值的判断变得复杂。
- 捕获异常具体的子类,而不是Exception,更不是throwable。这样会捕获所有的错误,包括JVM抛出的无法处理的严重错误。
- 切记更别忽视任何一个异常(catch住了不做任何处理),即使现在能确保不影响逻辑的正常运行,但是对于将来谁都无法保证代码会如何改动,别给自己挖坑。
- 不要使用异常当作控制流程来使用,这是一个很奇葩也很影响性能的做法。
- 清理资源,释放连接等操作一定要放在finally代码块中,防止内存泄漏,如果finally块处理的逻辑比较多且模块化,我们可以封装成工具方法调用,代码会比较简洁。
3.2 转转异常监控和上报的实践
public String doSomething(String arg) {
try {
return method1(arg);
} catch (Exception e) {
log.error("call method1 error msg={}", e.getMessage());
// do 报警相关逻辑
} finally {
// do close resource
}
return null;
}
ASMJavassistByteCode
premain3.3 ASM+javaAgent实现异常信息的统一上报
public static void premain(String arg, Instrumentation inst) {
LOG.info("******** AgentApplication.premain executing, String Param: {}********", arg);
inst.addTransformer(new CustomClassFileTransformer(), true);
LOG.info("******** AgentApplication premain executed ********");
}
@Override
public byte[] transform(ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
// 判断当前类是否需要增强
if (!needEnhance(className)) {
return classfileBuffer;
}
try {
ClassReader cr = new ClassReader(className);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
CustomClassVisitor classVisitor = new CustomClassVisitor(cw);
cr.accept(classVisitor, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
} catch (IOException e) {
LOG.warn("desc=CustomClassFileTransformer.transform, className:{} Exception:{}", className, e);
}
return classfileBuffer;
}
@Override
public MethodVisitor visitMethod(int access, String methodName, String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, methodName, desc, signature, exceptions);
// 跳过忽略的方法,如构造方法 <init>, toString等
if (!SKIP_METHODS.contains(methodName) && mv != null) {
mv = new CustomMethodVisitor(mv, className, methodName);
}
return mv;
}
@Override
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
exceptionHandlers.add(handler);
super.visitTryCatchBlock(start, end, handler, type);
}
@Override
public void visitLineNumber(int line, Label start) {
if (exceptionHandlers.contains(start)) {
ExceptionProcessor.injectHandleLogic(this, className, methodName, line);
}
super.visitLineNumber(line, start);
}
/**
* 注入处理逻辑
* 调用异常处理方法 {@link ExceptionProcessor#process(Throwable, String, String, int)}
*
* @param visitor 方法visitor
* @param className 类名
* @param methodName 方法名
* @param lineNumber catch块开始的 行号(一个方法中可能由多个catch块,索引引入lineNumber,精准标识别异常位置)
*/
public static void injectHandleLogic(MethodVisitor visitor, String className, String methodName, int lineNumber) {
visitor.visitInsn(DUP);
visitor.visitLdcInsn(className);
visitor.visitLdcInsn(methodName);
visitor.visitLdcInsn(lineNumber);
visitor.visitMethodInsn(INVOKESTATIC, EXCEPTION_HANDLE_CLASS, EXCEPTION_HANDLE_METHOD, EXCEPTION_HANDLE_PARAM, false);
}
/**
* 处理异常的逻辑
* 这个方法里我们可以明确知道抛异常的类、方法、行号等异常信息,方便组装上报信息方便研发定位
* 方法签名请勿修改 {@link ExceptionProcessor#injectHandleLogic(MethodVisitor, String, String, int)}中调用
*
* @param exception 要处理的异常
* @param className 类名
* @param methodName 方法名
* @param lineNumber catch块开始的行号
* @param <T> 异常范型
*/
public static <T extends Throwable> void process(T exception, String className, String methodName, int lineNumber) {
try {
className = className.replace(File.separator, ".");
String itemName = generateItemNameAfterFilter(exception.getClass().getSimpleName(), className, methodName);
if (StringUtil.isEmpty(itemName)) {
return;
}
// 告警逻辑的处理
ZzMonitor.sumWithAlarm(itemName, 1, String.valueOf(lineNumber), true);
} catch (RuntimeException e) {
LOG.error("desc=ExceptionProcessor.process error", e);
}
}
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<!--修改为你自己的类名全路径-->
<Premain-Class>com.****.AgentApplication</Premain-Class>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
-javaagent:./lib/auto-monitor-alarm-1.0.0.jar

四、总结
JavaAgentASM参考
作者简介
边栏推荐
猜你喜欢

MMdet的Resnet卷积替换成Ghost卷积组所出现的问题

ruoyi框架中添加sharding sphere5.0.0分表(通过spi添加自定义分表策略)

pod安全策略(PSP)

微博评论架构设计

保障饮用水安全!番禺沙湾水道水质在线监测系统通过验收

QT learning 15 separation of user interface and business logic

The use of Fibonacci sequence and bubble sort in C language

高效远程办公的基石:有效沟通 |社区征文

初次使用 eolink 感受

新版CorelDRAW Technical Suite2022最新详细功能介绍
随机推荐
保障饮用水安全!番禺沙湾水道水质在线监测系统通过验收
Exclusive interview with CTO: the company has deepened the product layout and accelerated the technological innovation of domestic EDA
记一次 MSI 笔记本 GE63 播放网页视频 闪屏和随机发绿 问题解决
Unity learning notes --vector3 how to set default parameters
Cornerstone of efficient remote office: effective communication | community essay solicitation
毕业5年,我问遍了身边的大佬,总结了他们的学习方法
信息技术应用创新专业人员(数据库)中级培训火热招生中(7月6-10日)
Nature | biosynthetic potential of global marine microbiome
ruoyi框架中添加sharding sphere5.0.0分表(通过spi添加自定义分表策略)
服务数百万开发者,首届 Techo Day 腾讯技术开放日发布 7 款“轻量级”产品
普通用户使用vscode登录ssh编辑root文件
专访 SUSS NiFT 负责人:Web3 的未来离不开“人人为我,我为人人”的治理
Safety innovation practice | Haitai Fangyuan was invited to participate in the technical exchange Seminar on "network information innovation and value co creation in the digital age"
leetcode刷题:字符串07(重复的子字符串)
ESP8266简介:三种编程方式「建议收藏」
开源机器学习平台
【HBZ分享】Semaphore 与 CountDownLatch原理
AOSP ~ Logcat 持久化
2022 amination process test question simulation test question bank and online simulation test
Qt学习09 计算器界面代码重构