content: package com.alibaba.jvm.sandbox.repeater.plugin.java;
  
  import com.google.common.collect.Maps;
  
  import java.lang.reflect.Proxy;
  import java.util.Map;
  
  /**
   * {@link JavaInstanceCache}
   * <p>
   * Java实例缓存，作用是将拦截到的JavaEntrance缓存起来，作为{@link JavaRepeater}获取java运行实例的补充
   * <p>
   * 该方法的局限性在于，必须该实例的埋点被采样到
   * </p>
   *
   * @author zhaoyb1990
   */
  class JavaInstanceCache {
  
      /**
       * key   : className
       * value : instance
       */
      private static Map<String, Object> CACHED = Maps.newConcurrentMap();
  
  
      /**
       * 根据实例的类名缓存
       * <p>
       * 注意问题:
       * 1. 多实例问题可能导致回放失败
       * </p>
       *
       * @param instance 实例
       */
      static void cacheInstance(Object instance) {
          if (instance != null) {
              Class<?> clazz;
              if (Proxy.isProxyClass(instance.getClass())) {
                  clazz = Proxy.getInvocationHandler(instance).getClass();
              } else {
                  clazz = instance.getClass();
              }
              CACHED.put(clazz.getCanonicalName(), instance);
          }
      }
  
      /**
       * 通过类找到实例
       * <p>
       * 注意问题：
       * 1. 实例的缓存时机是被回放的埋点被采样到（否则sandbox无法感知到实例）
       * </p>
       *
       * @param className 类全名
       * @return 实例
       */
      static Object getInstance(String className) {
          return CACHED.get(className);
      }
  }
  