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); } }