From de63b63d8264efc9c81aa667546d028859b7a90c Mon Sep 17 00:00:00 2001 From: Alexander Kriegisch Date: Sat, 8 Jan 2022 16:06:51 +0700 Subject: [PATCH] Add test for Java 11 constant-dynamic Relates to #68. Signed-off-by: Alexander Kriegisch --- tests/bugs198/github_68/Application.java | 20 ++++++ tests/bugs198/github_68/Generator.java | 67 ++++++++++++++++++ tests/bugs198/github_68/MyAspect.aj | 5 ++ tests/bugs198/github_68/condy.jar | Bin 0 -> 515 bytes .../systemtest/ajc198/AllTestsAspectJ198.java | 3 + .../systemtest/ajc198/Bugs198Java11Tests.java | 32 +++++++++ .../org/aspectj/systemtest/ajc198/ajc198.xml | 13 ++++ 7 files changed, 140 insertions(+) create mode 100644 tests/bugs198/github_68/Application.java create mode 100644 tests/bugs198/github_68/Generator.java create mode 100644 tests/bugs198/github_68/MyAspect.aj create mode 100644 tests/bugs198/github_68/condy.jar create mode 100644 tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Java11Tests.java diff --git a/tests/bugs198/github_68/Application.java b/tests/bugs198/github_68/Application.java new file mode 100644 index 000000000..47eeaa4f4 --- /dev/null +++ b/tests/bugs198/github_68/Application.java @@ -0,0 +1,20 @@ +import java.lang.invoke.ConstantBootstraps; +import java.util.concurrent.Callable; + +public class Application { + public static void main(String[] args) throws Exception { + Callable first = new CondyCallable(); + Callable second = new CondyCallable(); + if (!(first.call() == second.call())) + throw new RuntimeException("Non-identical ConstantDynamic values (should never happen)"); + } + + /** + * Class {@link CondyCallable} dispatches to this constructor via {@link ConstantBootstraps#invoke} + * in order to initialise a dynamic constant value. The constructor should be executed exactly once, + * no matter how many times {@link CondyCallable#call} is called. + */ + public Application() { + System.out.println("Sample instance created"); + } +} diff --git a/tests/bugs198/github_68/Generator.java b/tests/bugs198/github_68/Generator.java new file mode 100644 index 000000000..ea34c5b3b --- /dev/null +++ b/tests/bugs198/github_68/Generator.java @@ -0,0 +1,67 @@ +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.ConstantDynamic; +import org.objectweb.asm.Handle; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * This class was created by ASM-ifying a class generated by Byte Buddy. + * Its purpose it to create a class CondyCallable making use of + * dynamic class-file constants, a Java 11 feature introduced by JEP 309. + * + * @see https://openjdk.java.net/jeps/309 + */ +public class Generator implements Opcodes { + + private static final String CLASS_FILE = "CondyCallable.class"; + + public static void main(String[] args) throws IOException { + try (FileOutputStream fos = new FileOutputStream(CLASS_FILE)) { + fos.write(getClassBytes()); + } + System.out.println(CLASS_FILE + " generated successfully"); + } + + private static byte[] getClassBytes() { + ClassWriter classWriter = new ClassWriter(0); + classWriter.visit(V11, ACC_PUBLIC | ACC_SUPER, "CondyCallable", null, "java/lang/Object", new String[] { "java/util/concurrent/Callable" }); + createDefaultConstructor(classWriter); + createMethod_call(classWriter); + classWriter.visitEnd(); + return classWriter.toByteArray(); + } + + private static void createDefaultConstructor(ClassWriter classWriter) { + MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "", "()V", null, null); + methodVisitor.visitCode(); + methodVisitor.visitVarInsn(ALOAD, 0); + methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + methodVisitor.visitInsn(RETURN); + methodVisitor.visitMaxs(1, 1); + methodVisitor.visitEnd(); + } + + private static void createMethod_call(ClassWriter classWriter) { + MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "call", "()Ljava/lang/Object;", null, new String[] { "java/lang/Exception" }); + methodVisitor.visitCode(); + methodVisitor.visitLdcInsn( + // Create constant-dynamic instruction + new ConstantDynamic( + // Dummy name + "_", + // Constant type + "LApplication;", + // Bootstrap method: ConstantBootstraps::invoke, dispatching to an existing method/constructor + new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/ConstantBootstraps", "invoke", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;", false), + // Bootstrap method arguments: here we simply dispatch to the constructor of class Application + new Handle(Opcodes.H_NEWINVOKESPECIAL, "Application", "", "()V", false)) + ); + methodVisitor.visitInsn(ARETURN); + methodVisitor.visitMaxs(1, 1); + methodVisitor.visitEnd(); + } + +} diff --git a/tests/bugs198/github_68/MyAspect.aj b/tests/bugs198/github_68/MyAspect.aj new file mode 100644 index 000000000..1a329dfa0 --- /dev/null +++ b/tests/bugs198/github_68/MyAspect.aj @@ -0,0 +1,5 @@ +public aspect MyAspect { + before() : execution(*.new(..)) && !within(MyAspect) { + System.out.println(thisJoinPoint); + } +} diff --git a/tests/bugs198/github_68/condy.jar b/tests/bugs198/github_68/condy.jar new file mode 100644 index 0000000000000000000000000000000000000000..75fe7e5b88d6e168858d638cc937a422369e357d GIT binary patch literal 515 zcmWIWW@Zs#U|`^2cwDOya^&BpGvSO33^q&*48lNB=lr~sO6SC!oW!J@RK4V!#Ny)G zz|&rb9Yk!C z;NEGzcFWN&=JI!EYR}Fow%dQto3R1%JUd^^ync7z zdo5ncwr3VrA&wclf_5CX_||Ha-fP+R$5Vl+^wfmR@;vVg0T(8^PE>pyBX<0=L+zl4i1@1*uc<3$ zxOcW$)n-mgtH`tFwhiA`HQ}DBc-#y1_P#02i798N-d$lKu=i(&>?f6t|K_LM)ouF2 zT+X>V;_}4%?Sv; zEL0iP@GW*%=t<*GI~SY3SnnbJv0G^B(#*%|b61+iA3JHgspJyZO}n|5EoY}}%@6Qq zWU^<#6%#7JxBvkKFo`u@xS*1Z3=#~?0_*&9SZ**{p0y1C(bH1+pQZrm0B=?{kO_=H Nm + + + + + + + + + + + + + -- 2.39.5