code: public void fire(Object event) {
      LOG.debug("[{}] Firing an instance of {}: {}", logPrefix, event.getClass(), event);
      // if the exact match thing gets too cumbersome, we can reconsider, but I'd like to avoid
      // scanning all the keys with instanceof checks.
      Class<?> eventClass = event.getClass();
      for (Consumer<?> l : listeners.get(eventClass)) {
        @SuppressWarnings("unchecked")
        Consumer<Object> listener = (Consumer<Object>) l;
        LOG.debug("[{}] Notifying {} of {}", logPrefix, listener, event);
        listener.accept(event);
      }
    }
docs: Sends an event that will notify any registered listener for that class.
  
  <p>Listeners are looked up by an <b>exact match</b> on the class of the object, as returned by
  {@code event.getClass()}. Listeners of a supertype won't be notified.
  
  <p>The listeners are invoked on the calling thread. It's their responsibility to schedule event
  processing asynchronously if needed.