通过群内产品发的用户邮箱查到了用户id,再根据接口的相关日志结合uid在日志平台进行关联查询,查到日志后,再拿到traceId进行链路查询,果不其然,发现了异常日志,如下部分日志所示
java.lang.UnsupportedOperationException: null
at 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 List 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 List 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 List asList(T... a) {
return new ArrayList<>(a);
}
emm,看起来很简单啊,没问题啊,咋会报错呢?别着急,咱们在点开这个ArrayList
瞅瞅
private static class ArrayList extends AbstractList
implements 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
异常,跟线上报错一模一样!!