code: @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
      public <T, R extends Reference<T>> R track(T obj, Class<R> type, Runnable runnable){
          Class clazz = type;
          Reference ref;
          if(clazz==WeakReference.class)
              ref = new WeakReference(obj, this);
          else if(clazz==SoftReference.class)
              ref = new SoftReference(obj, this);
          else if(clazz==PhantomReference.class)
              ref = new PhantomReference(obj, this);
          else
              throw new ImpossibleException();
  
          tracked.put(ref, runnable);
          return (R)ref;
      }
docs: tracks the given {@code obj} using specified reference {@code type}.<br>
  Specified {@code runnable} is executed when {@code obj} gets garbage collected.
  
  @param obj       object needs to be tracked
  @param type      type of reference to be used for tracking
  @param runnable  runnable to be executed when {@code obj} gets garbage collected
  
  @return the {@link java.lang.ref.Reference} created for {@code obj}
  
  @see #track(Object, Runnable)