core/src/com/google/inject/internal/InjectorImpl.java
private <T> BindingImpl<T> getJustInTimeBinding(Key<T> key, Errors errors, JitLimitation jitType)
      throws ErrorsException {

    boolean jitOverride = isProvider(key) || isTypeLiteral(key) || isMembersInjector(key);
    synchronized (state.lock()) {
      // first try to find a JIT binding that we've already created
      for (InjectorImpl injector = this; injector != null; injector = injector.parent) {
        @SuppressWarnings("unchecked") // we only store bindings that match their key
        BindingImpl<T> binding = (BindingImpl<T>) injector.jitBindings.get(key);

        if (binding != null) {
          // If we found a JIT binding and we don't allow them,
          // fail.  (But allow bindings created through TypeConverters.)
          if (options.jitDisabled
              && jitType == JitLimitation.NO_JIT
              && !jitOverride
              && !(binding instanceof ConvertedConstantBindingImpl)) {
            throw errors.jitDisabled(key).toException();
          } else {
            return binding;
          }
        }
      }

      // If we previously failed creating this JIT binding and our Errors has
      // already recorded an error, then just directly throw that error.
      // We need to do this because it's possible we already cleaned up the
      // entry in jitBindings (during cleanup), and we may be trying
      // to create it again (in the case of a recursive JIT binding).
      // We need both of these guards for different reasons
      // failedJitBindings.contains: We want to continue processing if we've never
      //   failed before, so that our initial error message contains
      //   as much useful information as possible about what errors exist.
      // errors.hasErrors: If we haven't already failed, then it's OK to
      //   continue processing, to make sure the ultimate error message
      //   is the correct one.
      // See: ImplicitBindingsTest#testRecursiveJitBindingsCleanupCorrectly
      // for where this guard compes into play.
      if (failedJitBindings.contains(key) && errors.hasErrors()) {
        throw errors.toException();
      }
      return createJustInTimeBindingRecursive(key, errors, options.jitDisabled, jitType);
    } // end synchronized(state.lock())
  }
private <T> BindingImpl<T> getJustInTimeBinding(Key<T> key, Errors errors, JitLimitation jitType)
      throws ErrorsException {

    boolean jitOverride = isProvider(key) || isTypeLiteral(key) || isMembersInjector(key);
    synchronized (state.lock()) {
      // first try to find a JIT binding that we've already created
      for (InjectorImpl injector = this; injector != null; injector = injector.parent) {
        @SuppressWarnings("unchecked") // we only store bindings that match their key
        BindingImpl<T> binding = (BindingImpl<T>) injector.jitBindings.get(key);

        if (binding != null) {
          // If we found a JIT binding and we don't allow them,
          // fail.  (But allow bindings created through TypeConverters.)
          if (options.jitDisabled
              && jitType == JitLimitation.NO_JIT
              && !jitOverride
              && !(binding instanceof ConvertedConstantBindingImpl)) {
            throw errors.jitDisabled(key).toException();
          } else {
            return binding;
          }
        }
      }

      // If we previously failed creating this JIT binding and our Errors has
      // already recorded an error, then just directly throw that error.
      // We need to do this because it's possible we already cleaned up the
      // entry in jitBindings (during cleanup), and we may be trying
      // to create it again (in the case of a recursive JIT binding).
      // We need both of these guards for different reasons
      // failedJitBindings.contains: We want to continue processing if we've never
      //   failed before, so that our initial error message contains
      //   as much useful information as possible about what errors exist.
      // errors.hasErrors: If we haven't already failed, then it's OK to
      //   continue processing, to make sure the ultimate error message
      //   is the correct one.
      // See: ImplicitBindingsTest#testRecursiveJitBindingsCleanupCorrectly
      // for where this guard compes into play.
      if (failedJitBindings.contains(key) && errors.hasErrors()) {
        throw errors.toException();
      }
      return createJustInTimeBindingRecursive(key, errors, options.jitDisabled, jitType);
    } // end synchronized(state.lock())
  }
Returns a just-in-time binding for {@code key}, creating it if necessary.

@throws ErrorsException if the binding could not be created.