Relates to #68. Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>tags/V1_9_8
@@ -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"); | |||
} | |||
} |
@@ -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 <tt>CondyCallable</tt> 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, "<init>", "()V", null, null); | |||
methodVisitor.visitCode(); | |||
methodVisitor.visitVarInsn(ALOAD, 0); | |||
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()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", "<init>", "()V", false)) | |||
); | |||
methodVisitor.visitInsn(ARETURN); | |||
methodVisitor.visitMaxs(1, 1); | |||
methodVisitor.visitEnd(); | |||
} | |||
} |
@@ -0,0 +1,5 @@ | |||
public aspect MyAspect { | |||
before() : execution(*.new(..)) && !within(MyAspect) { | |||
System.out.println(thisJoinPoint); | |||
} | |||
} |
@@ -22,6 +22,9 @@ public class AllTestsAspectJ198 { | |||
if (LangUtil.is9VMOrGreater()) { | |||
suite.addTest(CompileWithReleaseTests.suite()); | |||
} | |||
if (LangUtil.is11VMOrGreater()) { | |||
suite.addTest(Bugs198Java11Tests.suite()); | |||
} | |||
if (LangUtil.is17VMOrGreater()) { | |||
suite.addTest(SanityTestsJava17.suite()); | |||
suite.addTest(Ajc198TestsJava.suite()); |
@@ -0,0 +1,32 @@ | |||
/******************************************************************************* | |||
* Copyright (c) 2021 Contributors | |||
* All rights reserved. This program and the accompanying materials | |||
* are made available under the terms of the Eclipse Public License v 2.0 | |||
* which accompanies this distribution, and is available at | |||
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt | |||
*******************************************************************************/ | |||
package org.aspectj.systemtest.ajc198; | |||
import junit.framework.Test; | |||
import org.aspectj.testing.XMLBasedAjcTestCase; | |||
import org.aspectj.testing.XMLBasedAjcTestCaseForJava11OrLater; | |||
/** | |||
* @author Alexander Kriegisch | |||
*/ | |||
public class Bugs198Java11Tests extends XMLBasedAjcTestCaseForJava11OrLater { | |||
public void testGitHub_68() { | |||
runTest("correctly weave code using constant-dynamic"); | |||
} | |||
public static Test suite() { | |||
return XMLBasedAjcTestCase.loadSuite(Bugs198Java11Tests.class); | |||
} | |||
@Override | |||
protected java.net.URL getSpecFile() { | |||
return getClassResource("ajc198.xml"); | |||
} | |||
} |
@@ -3,6 +3,19 @@ | |||
<suite> | |||
<!-- https://github.com/eclipse/org.aspectj/issues/68 --> | |||
<ajc-test dir="bugs198/github_68" vm="11" title="correctly weave code using constant-dynamic"> | |||
<compile files="Application.java MyAspect.aj" options="-11" inpath="condy.jar"/> | |||
<run class="Application"> | |||
<stdout> | |||
<line text="execution(CondyCallable())" /> | |||
<line text="execution(CondyCallable())" /> | |||
<line text="execution(Application())" /> | |||
<line text="Sample instance created" /> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<!-- https://github.com/eclipse/org.aspectj/issues/105 --> | |||
<ajc-test dir="bugs198/github_105" vm="8" title="ITD annotation with mandatory parameter via aspectpath"> | |||
<compile files="FooAnnotation.java BarAnnotation.java FooAspect.aj" options="-8" outjar="aspect.jar"/> |