文章目录
- 一、cat log.log | grep 流水号 引发的惨案
- 二、Collections.sort排序long型强转int型引发的惨案
一、cat log.log | grep 流水号 引发的惨案
接口报错,查看日志是空指针,但是没有详细的报错信息。
以为是日志打印格式的问题,遂改变了打印格式,发现还是没有详细错误信息。
网上搜索后推荐JVM参数加上-XX:-OmitStackTraceInFastThrow。
觉得动JVM参数不太放心,于是想到了Arthas工具。
寻找arthas的路径:locate arthas-boot.jar
进入对应服务的docker容器内部:docker exec -it pid /bin/bash
然后进入到arthas 的jar包目录,启动arthas java -jar arthas-boot.jar
选择进程(输入[]内编号(不是PID)回车),一般情况就只有一个,输入1即可
trace 命令能渲染和统计整个调用链路上的所有性能开销和追踪调用链路。
trace
使用trace命令查看方法内部每个方法的耗时 trace demo.Test queryUpgradeOffer
除了显示方法的耗时,还会显示是在哪个方法抛出了异常。找到是在convert2QueryOfferListRequest抛出了异常
继续使用trace命令查看convert2QueryOfferListRequest方法执行的耗时 trace demo.Test convert2QueryOfferListRequest
然后就能看到是在哪一行抛出了异常
通过排查代码发现是写错了map的key,导致值不存在抛出了空指针。
然后测试同事在群里发了一张截图,我看到了详细的堆栈信息,整个人瞬间不好了
忽然想起来了grep 的 -A -B -C三个参数
然后cat log.log | grep 流水号 -A 5 果然显示出了完整的堆栈信息。
二、Collections.sort排序long型强转int型引发的惨案
怪事天天有,今天特别多。
测试说我返回的数据顺序反了,我仔细差了一下代码,确认是写了排序,还是逆序,但是返回的结果就是正序,奇了怪了。
遇事不决,阿尔萨斯!
watch命令能观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参
watch
使用watch命令查看一下排序方法的参数和返回值,以及方法执行前后参数的变化
watch demo.Test calcRemainderTime “{params,returnObj}” -x 4 -b -s -n 4
发现排序后确实是逆序了,那问题确实出在排序方法上!
看了一下排序方法,确认是逆序,那就只可能是long型强转int型,精度丢失导致排序异常。
写个demo校验一下猜想。
public class SortTest {
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
Student student1 = new Student(18,1722095999999L);
Student student2 = new Student(19,1711468799999L);
Student student3 = new Student(12,1709567999999L);
Student student4 = new Student(18,1708567999999L);
list.add(student1);
list.add(student3);
list.add(student2);
list.add(student4);
// Collections.sort(list,(o1,o2)->o2.getAge()-o1.getAge());
Collections.sort(list,(o1,o2)->(int)(o2.getTime()-o1.getTime()));
for (Student student : list) {
System.out.println(student.getTime());
}
System.out.println("================第二次排序====================");
Collections.sort(list,(o1,o2)->{
if(o2.getTime()>o1.getTime()){
return 1;
}else if(o2.getTime()<o1.getTime()){
return -1;
}else {
return 0;
}
});
for (Student student : list) {
System.out.println(student.getTime());
}
}
static class Student{
private int age;
private long time;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public Student(int age, long time) {
this.age = age;
this.time = time;
}
}
}
执行结果如下
1711468799999
1709567999999
1722095999999
================第二次排序====================
1722095999999
1711468799999
1709567999999
1708567999999
确实是long型强转int型导致的排序异常,而测试的正序可能恰好是一个巧合。
故:排序时如果排序字段不是int型,不能强转成int型,精度丢失后排序会异常。