From c2e45de4f4ee6b778d4987ddfbf58c2f4d5c722f Mon Sep 17 00:00:00 2001 From: Fan Lin Date: Tue, 28 Sep 2021 20:49:31 +0800 Subject: [PATCH] Revert "Fixed method reference" --- .../demo/lambda/Function1Throwable.java | 9 - .../com/alibaba/demo/lambda/LambdaDemo.java | 218 --------------- .../com/alibaba/demo/lambda/StaticMethod.java | 15 -- .../alibaba/demo/lambda/LambdaDemoTest.java | 89 ------- .../agent/handler/BaseClassHandler.java | 4 +- .../agent/handler/SourceClassHandler.java | 249 +----------------- 6 files changed, 6 insertions(+), 578 deletions(-) delete mode 100644 demo/java-demo/src/main/java/com/alibaba/demo/lambda/Function1Throwable.java delete mode 100644 demo/java-demo/src/main/java/com/alibaba/demo/lambda/LambdaDemo.java delete mode 100644 demo/java-demo/src/main/java/com/alibaba/demo/lambda/StaticMethod.java delete mode 100644 demo/java-demo/src/test/java/com/alibaba/demo/lambda/LambdaDemoTest.java diff --git a/demo/java-demo/src/main/java/com/alibaba/demo/lambda/Function1Throwable.java b/demo/java-demo/src/main/java/com/alibaba/demo/lambda/Function1Throwable.java deleted file mode 100644 index a34e43e..0000000 --- a/demo/java-demo/src/main/java/com/alibaba/demo/lambda/Function1Throwable.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.alibaba.demo.lambda; - -/** - * @author jim - */ -@FunctionalInterface -public interface Function1Throwable { - R apply(T t) throws Throwable; -} diff --git a/demo/java-demo/src/main/java/com/alibaba/demo/lambda/LambdaDemo.java b/demo/java-demo/src/main/java/com/alibaba/demo/lambda/LambdaDemo.java deleted file mode 100644 index be87f5f..0000000 --- a/demo/java-demo/src/main/java/com/alibaba/demo/lambda/LambdaDemo.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.alibaba.demo.lambda; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Stream; - -/** - * @author jim - */ -@SuppressWarnings("unused") -public class LambdaDemo { - - public void methodReference() { - consumesRun(this::run); - } - - private void consumesRun(Runnable r) { - r.run(); - } - - private void run() { - blackHole(); - } - - public String methodReference0() { - return consumes0(this::function0); - } - - private String consumes0(Supplier function0) { - return function0.get(); - } - - private String function0() { - return "Hello"; - } - - public String methodReference1() { - return consumes1(this::function1); - } - - private String consumes1(Function function) { - return function.apply(1); - } - - private String function1(Integer i) { - return String.valueOf(i); - } - - public String methodReferenceThrows() { - return consumesThrows(this::function1Throwable); - } - - private String consumesThrows(Function1Throwable function) { - try { - return function.apply(1); - }catch (Throwable e) { - e.printStackTrace(); - } - return null; - } - - @SuppressWarnings("RedundantThrows") - private String function1Throwable(Integer i) throws Throwable{ - return String.valueOf(i); - } - - public String methodReference2() { - return consumes2(this::function2); - } - - private String consumes2(BiFunction function) { - return function.apply(1, .2); - } - - private String function2(Integer i, Double d) { - return i + String.valueOf(d); - } - - public String staticMethodReference1() { - return consumes1(StaticMethod::function1); - } - - public String staticMethodReference2() { - return consumes2(StaticMethod::function2); - } - - public void lambdaRun() { - consumes(() -> System.out.println("lambdaRun")); - } - - private void consumes(Runnable o) { - o.run(); - } - - public void methodReferenceNew() { - Object o = consumes(Object::new); - blackHole(o); - } - - private T consumes(Supplier s) { - return s.get(); - } - - private void blackHole(Object... ignore) {} - - public void array() { - Function arrayBooleanFunction = this::arrayBooleanFunction; - Function arrayBooleanFunction1 = this::arrayBoolFunction; - Function byteFunction = this::arrayByteFunction; - Function byteFunction1 = this::arrayByteFunction; - Function charFunction = this::arrayCharFunction; - Function charFunction1 = this::arrayCharFunction; - Function shortFunction = this::arrayShortFunction; - Function shortFunction1 = this::arrayShortFunction; - Function intFunction = this::arrayIntFunction; - Function intFunction1 = this::arrayIntegerFunction; - Function longFunction = this::arrayLongFunction; - Function longFunction1 = this::arrayLongFunction; - Function floatFunction = this::arrayFloatFunction; - Function floatFunction1 = this::arrayFloatFunction; - Function doubleFunction = this::arrayDoubleFunction; - Function doubleFunction1 = this::arrayDoubleFunction; - blackHole(arrayBooleanFunction, arrayBooleanFunction1, - byteFunction, byteFunction1, charFunction, charFunction1, shortFunction, shortFunction1, - intFunction, intFunction1, longFunction, longFunction1, floatFunction, floatFunction1, doubleFunction, - doubleFunction1 - ); - } - - private int[] arrayIntFunction(int[] arg) { - return arg; - } - - private Integer[] arrayIntegerFunction(Integer[] arg) { - return arg; - } - - private boolean[] arrayBoolFunction(boolean[] arg) { - return arg; - } - - private Boolean[] arrayBooleanFunction(Boolean[] arg) { - return arg; - } - - private byte[] arrayByteFunction(byte[] arg) { - return arg; - } - - private Byte[] arrayByteFunction(Byte[] arg) { - return arg; - } - - private char[] arrayCharFunction(char[] arg) { - return arg; - } - - private Character[] arrayCharFunction(Character[] arg) { - return arg; - } - - private short[] arrayShortFunction(short[] arg) { - return arg; - } - - private Short[] arrayShortFunction(Short[] arg) { - return arg; - } - - private long[] arrayLongFunction(long[] arg) { - return arg; - } - - private Long[] arrayLongFunction(Long[] arg) { - return arg; - } - - private float[] arrayFloatFunction(float[] arg) { - return arg; - } - - private Float[] arrayFloatFunction(Float[] arg) { - return arg; - } - - private double[] arrayDoubleFunction(double[] arg) { - return arg; - } - - private Double[] arrayDoubleFunction(Double[] arg) { - return arg; - } - - public void generic() { - Function genericFunction = this::genericFunction; - blackHole(genericFunction); - } - - public R genericFunction(T arg) { - //noinspection unchecked - return (R)arg; - } - - private void collects() { - long l = Stream.of("1", "2", "3") - .filter(v -> !"2".equals(v)) - .map(Long::parseLong) - .peek(this::blackHole) - .map(v -> new ArrayList(){{add(v);}}) - .flatMap(Collection::stream) - .mapToLong(Long::valueOf) - .sum(); - blackHole(l); - } -} diff --git a/demo/java-demo/src/main/java/com/alibaba/demo/lambda/StaticMethod.java b/demo/java-demo/src/main/java/com/alibaba/demo/lambda/StaticMethod.java deleted file mode 100644 index 437e606..0000000 --- a/demo/java-demo/src/main/java/com/alibaba/demo/lambda/StaticMethod.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.alibaba.demo.lambda; - -/** - * @author jim - */ -public class StaticMethod { - - public static String function1(Integer i) { - return "static" + i; - } - - public static String function2(Integer i, Double d) { - return "static" + i + d; - } -} diff --git a/demo/java-demo/src/test/java/com/alibaba/demo/lambda/LambdaDemoTest.java b/demo/java-demo/src/test/java/com/alibaba/demo/lambda/LambdaDemoTest.java deleted file mode 100644 index d44fb8b..0000000 --- a/demo/java-demo/src/test/java/com/alibaba/demo/lambda/LambdaDemoTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.alibaba.demo.lambda; - -import com.alibaba.testable.core.annotation.MockDiagnose; -import com.alibaba.testable.core.annotation.MockMethod; -import com.alibaba.testable.core.model.LogLevel; -import org.junit.jupiter.api.Test; - -import static com.alibaba.testable.core.matcher.InvokeVerifier.verify; -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * @author zcbbpo - */ -public class LambdaDemoTest { - private LambdaDemo lambdaDemo = new LambdaDemo(); - - @SuppressWarnings("unused") - @MockDiagnose(LogLevel.VERBOSE) - public static class Mock { - @MockMethod(targetClass = LambdaDemo.class, targetMethod = "run") - private void mockRun() { - } - - @MockMethod(targetClass = LambdaDemo.class) - private String function0() { - return "mock_function0"; - } - - @MockMethod(targetClass = LambdaDemo.class) - private String function1(Integer i) { - return "mock_function1"; - } - - @MockMethod(targetClass = LambdaDemo.class) - private String function2(Integer i, Double d) { - return "mock_function2"; - } - - @SuppressWarnings("RedundantThrows") - @MockMethod(targetClass = LambdaDemo.class) - private String function1Throwable(Integer i) throws Throwable{ - return "mock_function1Throwable"; - } - - @MockMethod(targetClass = StaticMethod.class, targetMethod = "function1") - public static String staticFunction1(Integer i) { - return "mock_staticFunction1"; - } - - - } - - @Test - public void shouldMockRun() { - lambdaDemo.methodReference(); - verify("mockRun").withTimes(1); - } - - @Test - public void shouldMockFunction0() { - String s = lambdaDemo.methodReference0(); - assertEquals(s, "mock_function0"); - } - - @Test - public void shouldMockFunction1() { - String s = lambdaDemo.methodReference1(); - assertEquals(s, "mock_function1"); - } - - @Test - public void shouldMockFunction2() { - String s = lambdaDemo.methodReference2(); - assertEquals(s, "mock_function2"); - } - - @Test - public void shouldMockFunction1Throws() { - String s = lambdaDemo.methodReferenceThrows(); - assertEquals(s, "mock_function1Throwable"); - } - - @Test - public void shouldMockStaticFunction1() { - String s = lambdaDemo.staticMethodReference1(); - assertEquals(s, "mock_staticFunction1"); - } - -} diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/BaseClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/BaseClassHandler.java index a987582..9fbbb67 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/BaseClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/BaseClassHandler.java @@ -19,9 +19,7 @@ abstract public class BaseClassHandler implements Opcodes { ClassNode cn = new ClassNode(); cr.accept(cn, 0); transform(cn); - - // flag 1 was auto compute max - ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_MAXS); + ClassWriter cw = new ClassWriter( 0); cn.accept(cw); return cw.toByteArray(); } diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java index 8ecfdb6..348ad11 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java @@ -6,17 +6,13 @@ import com.alibaba.testable.agent.util.BytecodeUtil; import com.alibaba.testable.agent.util.ClassUtil; import com.alibaba.testable.agent.util.MethodUtil; import com.alibaba.testable.core.util.LogUtil; -import org.objectweb.asm.Handle; import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.*; -import sun.invoke.util.Wrapper; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import static com.alibaba.testable.core.constant.ConstPool.CONSTRUCTOR; @@ -25,7 +21,6 @@ import static com.alibaba.testable.core.constant.ConstPool.CONSTRUCTOR; */ public class SourceClassHandler extends BaseClassHandler { - private AtomicInteger atomicInteger = new AtomicInteger(); private final String mockClassName; private final List injectMethods; private final Set invokeOps = new HashSet() {{ @@ -56,16 +51,13 @@ public class SourceClassHandler extends BaseClassHandler { memberInjectMethods.add(im); } } - - resolveMethodReference(cn); - for (MethodNode m : cn.methods) { - transformMethod(m, memberInjectMethods, newOperatorInjectMethods, cn); + transformMethod(m, memberInjectMethods, newOperatorInjectMethods); } } private void transformMethod(MethodNode mn, Set memberInjectMethods, - Set newOperatorInjectMethods, ClassNode cn) { + Set newOperatorInjectMethods) { LogUtil.verbose(" Found method %s", mn.name); if (mn.name.startsWith("$")) { // skip methods e.g. "$jacocoInit" @@ -119,7 +111,6 @@ public class SourceClassHandler extends BaseClassHandler { } } } - i++; } while (i < instructions.length); } @@ -336,234 +327,4 @@ public class SourceClassHandler extends BaseClassHandler { return Opcodes.INVOKEVIRTUAL == opcode && ClassUtil.isCompanionClassName(ownerClass); } - private void setFinalValue(Field ownerField, Object obj, Object value) throws Exception { - ownerField.setAccessible(true); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(ownerField, ownerField.getModifiers() & ~Modifier.FINAL); - ownerField.set(obj, value); - } - - private List fetchInvokeDynamicHandle(MethodNode mn) { - List handleList = new ArrayList(); - for (AbstractInsnNode instruction : mn.instructions) { - if (instruction.getOpcode() == Opcodes.INVOKEDYNAMIC) { - InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode)instruction; - handleList.add((Handle) invokeDynamicInsnNode.bsmArgs[1]); - } - } - return handleList; - } - - private void resolveMethodReference(ClassNode cn) { - List invokeDynamicList = new ArrayList(); - for (MethodNode method : cn.methods) { - List handleList = fetchInvokeDynamicHandle(method); - invokeDynamicList.addAll(handleList); - } - - // process for method reference - for (Handle handle : invokeDynamicList) { - if (handle.getName().startsWith("lambda$")) { - continue; - } - - int tag = handle.getTag(); - - if (tag == Opcodes.H_NEWINVOKESPECIAL) { - // lambda new method reference - continue; - } - boolean isStatic = tag == Opcodes.H_INVOKESTATIC; - - String desc = handle.getDesc(); - String parameters = desc.substring(desc.indexOf("(") + 1, desc.lastIndexOf(")")); - String returnType = desc.substring(desc.indexOf(")") + 1); - String[] parameterArray = parameters.split(";"); - int len = parameterArray.length; - for (String s : parameterArray) { - if (s.isEmpty()) { - len--; - } - } - String[] refineParameterArray = new String[len]; - int index = 0; - for (String s : parameterArray) { - if (!s.isEmpty()) { - refineParameterArray[index] = s; - index++; - } - } - - String lambdaName = String.format("Lambda$_%s_%d", handle.getName(), atomicInteger.incrementAndGet()); - MethodVisitor mv = cn.visitMethod(isStatic ? ACC_PUBLIC + ACC_STATIC : ACC_PUBLIC, lambdaName, desc, null, null); - - - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - if (!isStatic) { - mv.visitVarInsn(ALOAD, 0); - } - for (int i = 0; i < refineParameterArray.length; i++) { - String arg = refineParameterArray[i]; - mv.visitVarInsn(getLoadType(arg), isStatic ? i : i + 1); - } - - mv.visitMethodInsn(isStatic ? INVOKESTATIC : INVOKEVIRTUAL/*INVOKESPECIAL*/, handle.getOwner(), handle.getName(), desc, false); - - mv.visitInsn(getReturnType(returnType)); - - Label l1 = new Label(); - mv.visitLabel(l1); - - - String localVarOwner = handle.getOwner(); - - if (isStatic) { - for (int i = 0; i < refineParameterArray.length; i++) { - String localVar = refineParameterArray[i]; - if (!isPrimitive(localVar)) { - localVar = localVar.endsWith(";") ? localVar : localVar + ";"; - } - - if (localVar.isEmpty()) { - continue; - } - - mv.visitLocalVariable(String.format("o%d", i), localVar, null, l0, l1, i); - } - } else { - mv.visitLocalVariable("this", "L" + localVarOwner + ";", null, l0, l1, 0); - for (int i = 0; i < refineParameterArray.length; i++) { - String localVar = refineParameterArray[i]; - if (!isPrimitive(localVar) && !isPrimitiveArray(localVar)) { - localVar = localVar.endsWith(";") ? localVar : localVar + ";"; - } - if (localVar.isEmpty()) { - continue; - } - - mv.visitLocalVariable(String.format("o%d", i), localVar, null, l0, l1, i + 1); - } - } - // auto compute max - mv.visitMaxs(-1, -1); - mv.visitEnd(); - - try { - setFinalValue(handle.getClass().getDeclaredField("name"), handle, lambdaName); - if (!handle.getOwner().equals(cn.name) && isStatic) { - setFinalValue(handle.getClass().getDeclaredField("owner"), handle, cn.name); - } - } catch (Exception ignore) { - } - } - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - private boolean isPrimitive(String type) { - if (type.endsWith(";")) { - type = type.substring(0, type.length() - 1); - } - return BasicType.basicType(type.charAt(0)).isPrimitive(); - } - - private boolean isPrimitiveArray(String type) { - if (!type.startsWith("[")) { - return false; - } - if (type.endsWith(";")) { - type = type.substring(0, type.length() - 1); - } - - type = type.replace("[", ""); - return BasicType.basicType(type.charAt(0)).isPrimitive(); - } - - private int getReturnType(String returnType) { - return BasicType.basicType(returnType.charAt(0)).returnInsn; - } - - private int getLoadType(String arg) { - return BasicType.basicType(arg.charAt(0)).loadVarInsn; - } - - /** - * copy from java.lang.invoke.LambdaForm.BasicType - */ - enum BasicType { - /** - * all reference types - */ - L_TYPE('L', Object.class, Wrapper.OBJECT, ALOAD, ARETURN), - /** - * all primitive types - */ - I_TYPE('I', int.class, Wrapper.INT, ILOAD, IRETURN), - J_TYPE('J', long.class, Wrapper.LONG, LLOAD, LRETURN), - F_TYPE('F', float.class, Wrapper.FLOAT, FLOAD, FRETURN), - D_TYPE('D', double.class, Wrapper.DOUBLE, DLOAD, DRETURN), - V_TYPE('V', void.class, Wrapper.VOID, null, RETURN), - A_TYPE('[', Object[].class, Wrapper.OBJECT, ALOAD, ARETURN); - - private final char btChar; - private final Class btClass; - private final Wrapper btWrapper; - private final Integer loadVarInsn; - private final Integer returnInsn; - - BasicType(char btChar, Class btClass, Wrapper btWrapper, Integer loadVarInsn, Integer returnInsn) { - this.btChar = btChar; - this.btClass = btClass; - this.btWrapper = btWrapper; - this.loadVarInsn = loadVarInsn; - this.returnInsn = returnInsn; - } - - public char getBtChar() { - return btChar; - } - - public Class getBtClass() { - return btClass; - } - - public Integer getLoadVarInsn() { - return loadVarInsn; - } - - public Integer getReturnInsn() { - return returnInsn; - } - - public Wrapper getBtWrapper() { - return btWrapper; - } - - public boolean isPrimitive() { - return this != L_TYPE && this != A_TYPE; - } - - static BasicType basicType(char type) { - switch (type) { - case 'L': return L_TYPE; - case 'I': return I_TYPE; - case 'J': return J_TYPE; - case 'F': return F_TYPE; - case 'D': return D_TYPE; - case 'V': return V_TYPE; - case '[': return A_TYPE; - // all subword types are represented as ints - case 'Z': - case 'B': - case 'S': - case 'C': - return I_TYPE; - default: - throw new InternalError("Unknown type char: '"+type+"'"); - } - } - } - }