Откуда этот NPE?!

  • Автор темы Автор темы molor
  • Дата начала Дата начала
Статус
Закрыто для дальнейших ответов.

molor

Активный участник
Пользователь
Баллы
66
Есть в коде вот такое
Java:
if (timeouts == null) logger.log(Level.INFO, "null @ 1");
if (timeouts.get(address) == null) logger.log(Level.INFO, "null @ 2");

if (timeouts.containsKey(address) && timeouts.get(address).longValue() <= System.currentTimeMillis()) timeouts.remove(address);

Ни один из null'ов в начале не срабатывает, однако на последней строке иногда вылетает java.lang.NullPointerException. Из-за чего оно может вылетать?!
 
Значение у ключа может быть null.
 
Если так, то тем более вопрос, откуда NPE-то появляется, если такая операция допустима?
Или я неправильно Вас понял?
Ну ты проверяешь существование ключа. Ключ существует (т.е. не null). Но у ключа значение (value) может быть null. Т.е. timeouts.put(address, (Long) null);. В случае если NPE выплевывается и ты не знаешь почему, то лучше выводить в лог ключ-значение или же всю мапу.

UPD: А, лол. Вторая строчка. Вот тебе и one line if. Экономщики херовы.
Можешь ещё внезапно synchronized пользоваться. Но более ни чего не могу написать, т.к. ты по сути даже ничего не написал.
 
Но у ключа значение (value) может быть null.
Так второй if как раз проверяет на это, но он не сработал..

Содержимое HashMap я выводить не могу, потому что этот NPE непостоянен; к тому же это забьёт журнал сервера ненужной информацией.
Странность в том, что этот код может идеально проработать неделю, например, а может и сразу после запуска сервера выбросить это исключение. И я не понимаю, почему.
Дополнительная инфа: этот участок кода находится в асинхронном scheduler'е. Но я не думаю, что что-то извне может помешать ему выполниться.
 
А перед этим NPE выводится какой ниб "null @ x"? Ибо ты просто пишешь в лог что нуллик есть, и продолжаешь работу.

UPD: забыл что ты об этом написал. Выкладывай реализацию своего поделия.
 
А перед этим NPE выводится какой ниб "null @ x"? Ибо ты просто пишешь в лог что нуллик есть, и продолжаешь работу.
Нет, это эти два. Про продолжение работы так и задумано (проверки ведь временные и только для того, чтобы понять, почему появляется исключение).

Всё вместе это выглядит так:
JavaScript:
private HashMap<InetAddress, Long> timeouts = new HashMap<InetAddress, Long>();

...

if (timeouts.containsKey(address)) {
  return;
}

scheduler.runTaskLaterAsynchronously(plugin, () -> {
  // WTF
  if (timeouts == null) logger.log(Level.INFO, "null @ 1");
  if (timeouts.get(address) == null) logger.log(Level.INFO, "null @ 2");

  if (timeouts.containsKey(address) && timeouts.get(address).longValue() <= System.currentTimeMillis()) timeouts.remove(address);
}, 15L);

timeouts.put(address, System.currentTimeMillis() + 500L);

Смысл в том, чтобы внести адрес игрока в Map, и пока он там есть, делать ничего; спустя полминуты он должен автоматически убраться.
 
Нет, это эти два. Про продолжение работы так и задумано (проверки ведь временные и только для того, чтобы понять, почему появляется исключение).

Всё вместе это выглядит так:
JavaScript:
private HashMap<InetAddress, Long> timeouts = new HashMap<InetAddress, Long>();

...

scheduler.runTaskLaterAsynchronously(plugin, () -> {
  // WTF
  if (timeouts == null) logger.log(Level.INFO, "null @ 1");
  if (timeouts.get(address) == null) logger.log(Level.INFO, "null @ 2");

  if (timeouts.containsKey(address) && timeouts.get(address).longValue() <= System.currentTimeMillis()) timeouts.remove(address);
}, 15L);

timeouts.put(address, System.currentTimeMillis() + 500L);

Смысл в том, чтобы внести адрес игрока в Map, и пока он там есть, делать ничего; спустя полминуты он должен автоматически убраться.
Хрень какую то ты делаешь.
Java:
private final HashSet<InetAddress> timeouts = new HashSet<>();
//...

if (timeouts.contains(address)) {
  return;
}
scheduler.runTaskLaterAsynchronously(plugin, () -> {
    synchronized(timeouts) {
        timeouts.remove(address);
    }
}, 15L);

timeouts.put(address);

UPD: Перед внесением InetAddess проверь его на null - иногда все таки бывает и такое.
 
Последнее редактирование:
Java:
private final HashSet<InetAddress> timeouts = new HashSet<>();
//...
scheduler.runTaskLaterAsynchronously(plugin, () -> {
    synchronized(timeouts) {
        timeouts.remove(address);
    }
}, 15L);

timeouts.put(address);
Предоставленный мною код вырван из разных классов и по нему не понять всю логику.
Ладно, перескажу.

Есть Map, в которую вносится время, когда игрок последний раз что-то делал. Это время должно удалиться из Map через полсекунды. Но, если оно там есть и игрок снова что-то сделал, его не нужно удалять из Map, а только обновить, чтобы запущенная ранее через scheduler задача не удалила его и чтобы игрок не смог снова это что-то сделать. Вместе со старой задачей также запускается и новая, которая уже должна будет удалить это время. Но та самая проверка на время выбивает NPE.

Надо будет почитать про synchronized.
UPD: Перед внесением InetAddess проверь его на null - иногда все таки бывает и такое.
Да, встречал такое. Проверка на это за кадром осталась.
 
Есть Map, в которую вносится время, когда игрок последний раз что-то делал. Это время должно удалиться из Map через полсекунды. Но, если оно там есть и игрок снова что-то сделал, его не нужно удалять из Map, а только обновить, чтобы запущенная ранее через scheduler задача не удалила его и чтобы игрок не смог снова это что-то сделать. Вместе со старой задачей также запускается и новая, которая уже должна будет удалить это время. Но та самая проверка на время выбивает NPE.
В таком случае твой таск излишен. Просто при действии смотри вермя - если прошло больше, то ставишь заново, иначе обновляешь. А удалять одним таском раз в 5-10 секунд по всему списку, ежели такая опция интересует.
 
В таком случае твой таск излишен. Просто при действии смотри вермя - если прошло больше, то ставишь заново, иначе обновляешь. А удалять одним таском раз в 5-10 секунд по всему списку, ежели такая опция интересует.
Но это не отвечает на вопрос, откуда появляется NPE. Может быть, в конце концов я так и сделаю, но интерес по поводу происхождения проблемы от этого не пропадёт..
 
Но это не отвечает на вопрос, откуда появляется NPE. Может быть, в конце концов я так и сделаю, но интерес по поводу происхождения проблемы от этого не пропадёт..
Тут шедулер излишен.

Java:
    static WeakHashMap<Player, Long> usertime = new WeakHashMap<Player, Long>();
    static boolean check(Player user, long tmp) {
        long time = System.currentTimeMillis();
        Long last = usertime.get(user);
        if(last!= null) {
            if((time-last)<tmp) {
                return false;
            }
        }
        usertime.put(user, time);
        return true;
    }
 
Статус
Закрыто для дальнейших ответов.
Назад
Верх