diff --git a/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java b/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java index a8a271594..e358745b5 100644 --- a/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java +++ b/core/src/main/java/com/taobao/arthas/core/advisor/Enhancer.java @@ -42,6 +42,7 @@ import com.alibaba.bytekit.asm.location.filter.InvokeContainLocationFilter; import com.alibaba.bytekit.asm.location.filter.LocationFilter; import com.alibaba.bytekit.utils.AsmOpUtils; import com.alibaba.bytekit.utils.AsmUtils; +import com.taobao.arthas.common.Pair; import com.taobao.arthas.core.GlobalOptions; import com.taobao.arthas.core.advisor.SpyInterceptors.SpyInterceptor1; import com.taobao.arthas.core.advisor.SpyInterceptors.SpyInterceptor2; @@ -76,6 +77,7 @@ public class Enhancer implements ClassFileTransformer { private final Matcher methodNameMatcher; private final EnhancerAffect affect; private Set> matchingClasses = null; + private static final ClassLoader selfClassLoader = Enhancer.class.getClassLoader(); // 被增强的类的缓存 private final static Map/* Class */, Object> classBytesCache = new WeakHashMap, Object>(); @@ -320,14 +322,35 @@ public class Enhancer implements ClassFileTransformer { * * @param classes 类集合 */ - private void filter(Set> classes) { + private List, String>> filter(Set> classes) { + List, String>> filteredClasses = new ArrayList, String>>(); final Iterator> it = classes.iterator(); while (it.hasNext()) { final Class clazz = it.next(); - if (null == clazz || isSelf(clazz) || isUnsafeClass(clazz) || isUnsupportedClass(clazz) || isExclude(clazz)) { + boolean removeFlag = false; + if (null == clazz) { + removeFlag = true; + } else if (isSelf(clazz)) { + filteredClasses.add(new Pair, String>(clazz, "class loaded by arthas itself")); + removeFlag = true; + } else if (isUnsafeClass(clazz)) { + filteredClasses.add(new Pair, String>(clazz, "class loaded by Bootstrap Classloader, try to execute `options unsafe true`")); + removeFlag = true; + } else if (isExclude(clazz)) { + filteredClasses.add(new Pair, String>(clazz, "class is excluded")); + removeFlag = true; + } else { + Pair unsupportedResult = isUnsupportedClass(clazz); + if (unsupportedResult.getFirst()) { + filteredClasses.add(new Pair, String>(clazz, unsupportedResult.getSecond())); + removeFlag = true; + } + } + if (removeFlag) { it.remove(); } } + return filteredClasses; } private boolean isExclude(Class clazz) { @@ -341,7 +364,7 @@ public class Enhancer implements ClassFileTransformer { * 是否过滤Arthas加载的类 */ private static boolean isSelf(Class clazz) { - return null != clazz && isEquals(clazz.getClassLoader(), Enhancer.class.getClassLoader()); + return null != clazz && isEquals(clazz.getClassLoader(), selfClassLoader); } /** @@ -354,9 +377,31 @@ public class Enhancer implements ClassFileTransformer { /** * 是否过滤目前暂不支持的类 */ - private static boolean isUnsupportedClass(Class clazz) { - return clazz.isArray() || (clazz.isInterface() && !GlobalOptions.isSupportDefaultMethod) || clazz.isEnum() - || clazz.equals(Class.class) || clazz.equals(Integer.class) || clazz.equals(Method.class) || ClassUtils.isLambdaClass(clazz); + private static Pair isUnsupportedClass(Class clazz) { + if (ClassUtils.isLambdaClass(clazz)) { + return new Pair(Boolean.TRUE, "class is lambda"); + } + + if (clazz.isInterface() && !GlobalOptions.isSupportDefaultMethod) { + return new Pair(Boolean.TRUE, "class is interface"); + } + + if (clazz.equals(Integer.class)) { + return new Pair(Boolean.TRUE, "class is java.lang.Integer"); + } + + if (clazz.equals(Class.class)) { + return new Pair(Boolean.TRUE, "class is java.lang.Class"); + } + + if (clazz.equals(Method.class)) { + return new Pair(Boolean.TRUE, "class is java.lang.Method"); + } + + if (clazz.isArray()) { + return new Pair(Boolean.TRUE, "class is array"); + } + return new Pair(Boolean.FALSE, ""); } /** @@ -378,7 +423,12 @@ public class Enhancer implements ClassFileTransformer { : SearchUtils.searchSubClass(inst, SearchUtils.searchClass(inst, classNameMatcher)); // 过滤掉无法被增强的类 - filter(matchingClasses); + List, String>> filtedList = filter(matchingClasses); + if (!filtedList.isEmpty()) { + for (Pair, String> filted : filtedList) { + logger.info("ignore class: {}, reson: {}", filted.getFirst().getName(), filted.getSecond()); + } + } logger.info("enhance matched classes: {}", matchingClasses);