/**
  * Removes dirty entries from the cache. Calling System.currentTimeMillis() is costly so we
  * should try to limit calls to this method. This method will only trigger cleanup at most once
  * per 30s.
  */
 private void removeDirtyEntries() {
   long now = System.currentTimeMillis();
   if (now - lastCleanup < MINIMAL_CLEANUP_INTERVAL) {
     return;
   }
   lock.writeLock().lock();
   try {
     for (MethodInvocationKey key : new LinkedList<MethodInvocationKey>(store.keySet())) {
       if (key.isDirty()) {
         evict++;
         store.remove(key);
       }
     }
   } finally {
     lastCleanup = now;
     lock.writeLock().unlock();
   }
 }
      @Override
      public boolean equals(Object o) {
        if (this == o) {
          return true;
        }
        if (o == null || getClass() != o.getClass()) {
          return false;
        }

        MethodInvocationKey that = (MethodInvocationKey) o;

        if (isDirty() && that.isDirty()) {
          return true;
        }
        if (!eq(lookupClass, that.lookupClass)) {
          return false;
        }
        if (!methodName.equals(that.methodName)) {
          return false;
        }
        return eq(parameterTypes, that.parameterTypes);
      }