广州协会网站建设,品牌型网站有哪些,怎么做网站代理,网站中的搜索功能怎么做假ArrayList导致的线上事故…
线上事故回顾
晚饭时#xff0c;当我正沉迷于排骨煲肉质鲜嫩#xff0c;汤汁浓郁时#xff0c;产研沟通群内发出一条消息#xff0c;显示用户存在可用劵#xff0c;但进去劵列表却什么也没有#xff0c;并附含了一个视频。于是我一边吃了排…假ArrayList导致的线上事故…
线上事故回顾
晚饭时当我正沉迷于排骨煲肉质鲜嫩汤汁浓郁时产研沟通群内发出一条消息显示用户存在可用劵但进去劵列表却什么也没有并附含了一个视频。于是我一边吃了排骨一边查看消息点开了视频en~视频跟描述一样。但没有系统告警用户界面也没有明显的报错提示怀疑是小部分特殊情况导致的查看消息后几秒我直接被来处理问题擦只好把外卖盒重新盖好先去处理问题。
处理经过 通过群内产品发的用户邮箱查到了用户id再根据接口的相关日志结合uid在日志平台进行关联查询查到日志后再拿到traceId进行链路查询果不其然发现了异常日志如下部分日志所示 java.lang.UnsupportedOperationException: nullat java.util.AbstractList.add(AbstractList.java:148) ~[na:1.8.0_151]at java.util.AbstractList.add(AbstractList.java:108) ~[na:1.8.0_151]这UnsupportedOperationException是个什么玩意 Slf4j
SpringBootTest
public class Demo {public void test(Context context) { context.getList().add(皮皮虾);}}Data
class Context {private ListString list;}基本操作就是拿到上下文中的List然后再add一个元素 讲道理add操作是不会有问题的有问题的还得是List追根溯源让我康康这个List是怎么来的于是我一顿狂点来到了set这个list的位置 Slf4j
SpringBootTest
public class Demo {public void test(Context context) {context.setList(Arrays.asList(皮皮虾));}}Data
class Context {private ListString list;}context.setList(Arrays.asList(Code皮皮虾)); 这行看起来好像没问题啊Arrays.asList(T... a)我们平时也会用传入一个数组返回出一个List没啥问题呀 那我再试试add方法 ,擦问题复现了还真是Arrays.asList(T... a)生成的List的add方法报错,由于线上存在问题则先修改为以下代码上线也就是修改为我们平时正常的写法, 上线后观察了下日志群里回复已解决问题也让用户重试发现没问题自此问题解决。
追根溯源 进入asList方法发现底层new了一个ArrayList并将数组传入作为List的元素 SafeVarargs
SuppressWarnings(varargs)
public static T ListT asList(T... a) {return new ArrayList(a);
}emm看起来很简单啊没问题啊咋会报错呢?别着急咱们在点开这个ArrayList瞅瞅 private static class ArrayListE extends AbstractListEimplements RandomAccess, java.io.Serializable
{private static final long serialVersionUID -2764017481108945198L;private final E[] a;ArrayList(E[] array) {a Objects.requireNonNull(array);}// ... 省略
}擦这ArrayList是Arrays类的一个静态内部类不是我们经常用的java.util.ArrayList 继续看这个静态内部类ArrayList继承了AbstractList而且默认是没有实现add方法的.也就是说调用add方法会直接调用父类也就是AbstractList的add方法源码点开一看真相大白了.AbstractList的add方法直接抛出UnsupportedOperationException异常跟线上报错一模一样