diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/OmniClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/OmniClassHandler.java index 3ca5777..ffab665 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/OmniClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/OmniClassHandler.java @@ -5,13 +5,16 @@ import com.alibaba.testable.agent.handler.test.JUnit5Framework; import com.alibaba.testable.agent.util.AnnotationUtil; import com.alibaba.testable.agent.util.BytecodeUtil; import com.alibaba.testable.agent.util.ClassUtil; +import com.alibaba.testable.core.exception.ClassConstructionException; import com.alibaba.testable.core.util.CollectionUtil; +import com.alibaba.testable.core.util.LogUtil; import com.alibaba.testable.core.util.StringUtil; import com.alibaba.testable.core.util.TypeUtil; import org.objectweb.asm.Label; import org.objectweb.asm.Type; import org.objectweb.asm.tree.*; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -45,6 +48,8 @@ public class OmniClassHandler extends BaseClassHandler { JUnit4Framework.ANNOTATION_TEST, JUnit5Framework.ANNOTATION_TEST, JUnit5Framework.ANNOTATION_PARAMETERIZED_TEST }; + private static final Map[]> constructorParameterCache = new HashMap[]>(); + @Override protected void transform(ClassNode cn) { if (isInterfaceOrAtom(cn) || isUniqueConstructorClass(cn) || isUninstantiableClass(cn) || @@ -66,8 +71,12 @@ public class OmniClassHandler extends BaseClassHandler { extraParameterCount = PRELOADED_CLASSES.get(cn.superName).length; } else if (cn.superName.startsWith("java/")) { try { - Class superClazz = Class.forName(ClassUtil.toDotSeparatedName(cn.superName)); - Class[] constructorParameterTypes = TypeUtil.getBestConstructor(superClazz).getParameterTypes(); + Class[] constructorParameterTypes = constructorParameterCache.get(cn.superName); + if (constructorParameterTypes == null) { + Class superClazz = Class.forName(ClassUtil.toDotSeparatedName(cn.superName)); + constructorParameterTypes = TypeUtil.getBestConstructor(superClazz).getParameterTypes(); + constructorParameterCache.put(superClazz.getName(), constructorParameterTypes); + } if (constructorParameterTypes.length == 0) { constructor.instructions = invokeSuperWithoutTestableParameter(cn.superName, new String[0], start, end); extraParameterCount = 0; @@ -80,7 +89,8 @@ public class OmniClassHandler extends BaseClassHandler { extraParameterCount = constructorParameterTypes.length; } } catch (ClassNotFoundException e) { - constructor.instructions = invokeSuperWithTestableVoidParameter(cn.superName, start, end); + LogUtil.warn("[OmniConstructor] Failed to load class " + cn.superName); + constructor.instructions = invokeSuperWithoutTestableParameter(cn.superName, new String[0], start, end); } } else { constructor.instructions = invokeSuperWithTestableVoidParameter(cn.superName, start, end); diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/util/BytecodeUtil.java b/testable-agent/src/main/java/com/alibaba/testable/agent/util/BytecodeUtil.java index 57bea4b..3253706 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/util/BytecodeUtil.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/util/BytecodeUtil.java @@ -188,7 +188,7 @@ public class BytecodeUtil { }}; /** - * Java primitive type name to bytecode mapping + * java primitive type name to bytecode mapping */ public static Map PRIMITIVE_TYPE_NAME_MAP = new HashMap() {{ put("byte", String.valueOf((char)TYPE_BYTE)); @@ -202,7 +202,7 @@ public class BytecodeUtil { }}; /** - * Get stack impact of a specified ops code + * get stack impact of a specified ops code * @param bytecode ops code to check * @return stack change */ @@ -211,7 +211,7 @@ public class BytecodeUtil { } /** - * Make sure method has public access + * make sure method has public access * @param access original access mark * @return access mark with public flag */ @@ -223,7 +223,7 @@ public class BytecodeUtil { } /** - * Dump byte code to specified class file + * dump byte code to specified class file * @param cn original class node * @param dumpPath folder to store class file * @param bytes original class bytes