feat: cache constructor parameter types for efficiency

This commit is contained in:
金戟
2022-12-12 08:20:58 +08:00
parent d5c1f780de
commit ab87ef1fd0
2 changed files with 17 additions and 7 deletions

View File

@@ -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<String, Class<?>[]> constructorParameterCache = new HashMap<String, Class<?>[]>();
@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);

View File

@@ -188,7 +188,7 @@ public class BytecodeUtil {
}};
/**
* Java primitive type name to bytecode mapping
* java primitive type name to bytecode mapping
*/
public static Map<String, String> PRIMITIVE_TYPE_NAME_MAP = new HashMap<String, String>() {{
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