Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

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

Тема в разделе "Разработка плагинов для новичков", создана пользователем molor, 29 апр 2017.

Статус темы:
Закрыта.
  1. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Есть в коде вот такое
    Код:
    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. Из-за чего оно может вылетать?!
     
  2. Хостинг MineCraft
    <
  3. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Значение у ключа может быть null.
     
  4. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Если так, то тем более вопрос, откуда NPE-то появляется, если такая операция допустима?
    Или я неправильно Вас понял?
     
  5. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Ну ты проверяешь существование ключа. Ключ существует (т.е. не null). Но у ключа значение (value) может быть null. Т.е. timeouts.put(address, (Long) null);. В случае если NPE выплевывается и ты не знаешь почему, то лучше выводить в лог ключ-значение или же всю мапу.

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

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Так второй if как раз проверяет на это, но он не сработал..

    Содержимое HashMap я выводить не могу, потому что этот NPE непостоянен; к тому же это забьёт журнал сервера ненужной информацией.
    Странность в том, что этот код может идеально проработать неделю, например, а может и сразу после запуска сервера выбросить это исключение. И я не понимаю, почему.[DOUBLEPOST=1493468449,1493468390][/DOUBLEPOST]Дополнительная инфа: этот участок кода находится в асинхронном scheduler'е. Но я не думаю, что что-то извне может помешать ему выполниться.
     
  7. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    А перед этим NPE выводится какой ниб "null @ x"? Ибо ты просто пишешь в лог что нуллик есть, и продолжаешь работу.

    UPD: забыл что ты об этом написал. Выкладывай реализацию своего поделия.
     
  8. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Нет, это эти два. Про продолжение работы так и задумано (проверки ведь временные и только для того, чтобы понять, почему появляется исключение).

    Всё вместе это выглядит так:
    Код:
    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, и пока он там есть, делать ничего; спустя полминуты он должен автоматически убраться.
     
  9. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Хрень какую то ты делаешь.
    Код:
    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 - иногда все таки бывает и такое.
     
    Последнее редактирование: 29 апр 2017
  10. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Предоставленный мною код вырван из разных классов и по нему не понять всю логику.
    Ладно, перескажу.

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

    Надо будет почитать про synchronized.
    Да, встречал такое. Проверка на это за кадром осталась.
     
  11. Dereku

    Dereku Старожил

    Баллы:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    В таком случае твой таск излишен. Просто при действии смотри вермя - если прошло больше, то ставишь заново, иначе обновляешь. А удалять одним таском раз в 5-10 секунд по всему списку, ежели такая опция интересует.
     
  12. Автор темы
    molor

    molor Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    molore
    Но это не отвечает на вопрос, откуда появляется NPE. Может быть, в конце концов я так и сделаю, но интерес по поводу происхождения проблемы от этого не пропадёт..
     
  13. alexandrage

    alexandrage Администратор

    Баллы:
    173
    Skype:
    alexandr0116
    Тут шедулер излишен.

    Код:
        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;
        }
     
Статус темы:
Закрыта.

Поделиться этой страницей