【发布时间】:2020-01-29 13:16:33
【问题描述】:
我遇到了一个只发生在生产环境中的奇怪案例。
基本上,我们会保留每个用户最近的选项的历史记录,然后我们会像这样检索它们:
LinkedList l_recent = ApplicationEnvironment.getUserRecentOptions(username);
for (int i = 0; i < l_recent.size(); i++) {
l_recent.get(i); // When i == 2 throws a NPE
}
然而,stacktrace 是空的,get 方法的 javadoc 只描述了一个可能的异常:IndexOutOfBoundsException if index < 0 || index >= size
幸运的是,这只发生在极少数用户身上,我们通过清除最近选项的历史记录来修复它。
但我仍然想知道为什么这会引发 NPE。
我唯一的猜测是,由于此列表是针对每个用户的,因此可能会发生多次登录同一用户的情况,然后我们可能会同时调用 LinkedList 的 add 或 remove 方法
编辑 1
这里是完整的代码:
import java.util.*;
public class App {
static class Option {
private String name;
Option(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private static final HashMap<String, LinkedList<Option>> userOptions = new HashMap<>();
public static LinkedList<Option> getUserRecentOptions(String user) {
LinkedList<Option> options;
if (userOptions.containsKey(user)) {
options = userOptions.get(user);
} else {
options = new LinkedList<>();
userOptions.put(user, options);
}
return options;
}
public static void addRecentOptionToUser(String user, Option option){
LinkedList<Option> options = getUserRecentOptions(user);
for (int i = 0; i < options.size(); i++) {
Option opt = options.get(i);
if (opt.getName().equalsIgnoreCase(option.getName())) {
options.remove(i);
break;
}
}
options.addFirst(option);
// Max 4
if (options.size() > 5) {
options.removeLast();
}
}
public static void main() {
LinkedList<Option> recentOptions = getUserRecentOptions("demo");
for (int i = 0; i < recentOptions.size(); i++) {
recentOptions.get(i); // Throws NPE when i == 2 (sometimes...)
}
}
}
【问题讨论】:
-
这就是全部代码吗?似乎
l_recent = null(或类似的东西)正在某处发生。 -
这是真实代码还是简化版? NPE 是调用本身还是在
get内部抛出的? -
你大概不调用
List::get并忽略结果。显示真实代码(或者至少,比这个人为的例子更接近“真实”) -
@AnkurChrungoo:如果
l_recent是此代码所暗示的局部变量,则不会。再说一遍:如果代码是 OP 声称的那样,这不会发生......这就是为什么我们需要真实代码或至少更接近真实代码的东西。 -
@JoachimSauer 你去吧,不是局部变量..
标签: java