diff options
author | Andy Clement <aclement@pivotal.io> | 2022-01-10 08:06:56 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-10 08:06:56 -0800 |
commit | 254ba9e8bb201a912a326277b29a602b0054a826 (patch) | |
tree | dc32d2132386d3c73f1fc56065631e46d6d20dd9 | |
parent | 92779d0829d41d55cae300d4d4d5a67cff72916d (diff) | |
parent | 250aa63cb28f3915d32ad67b881bd1dad8222320 (diff) | |
download | aspectj-254ba9e8bb201a912a326277b29a602b0054a826.tar.gz aspectj-254ba9e8bb201a912a326277b29a602b0054a826.zip |
Merge pull request #111 from kriegaex/release-198
Add test for Java 11 constant-dynamic
-rw-r--r-- | docs/dist/doc/README-198.html | 22 | ||||
-rw-r--r-- | tests/bugs198/github_68/Application.java | 20 | ||||
-rw-r--r-- | tests/bugs198/github_68/Generator.java | 67 | ||||
-rw-r--r-- | tests/bugs198/github_68/MyAspect.aj | 5 | ||||
-rw-r--r-- | tests/bugs198/github_68/condy.jar | bin | 0 -> 515 bytes | |||
-rw-r--r-- | tests/src/test/java/org/aspectj/systemtest/ajc198/AllTestsAspectJ198.java | 3 | ||||
-rw-r--r-- | tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Java11Tests.java | 32 | ||||
-rw-r--r-- | tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml | 13 |
8 files changed, 156 insertions, 6 deletions
diff --git a/docs/dist/doc/README-198.html b/docs/dist/doc/README-198.html index 57165e5c0..7e30661da 100644 --- a/docs/dist/doc/README-198.html +++ b/docs/dist/doc/README-198.html @@ -89,12 +89,12 @@ <ul> <li> - The AspectJ compiler <tt>ajc</tt> (contained in the <tt>aspectjtools</tt> library) no longer works on JDKs 8 to 10. The minimum - compile-time requirement is now JDK 11 due to upstream changes in the Eclipse Java Compiler (subset of JDT Core), - which AspectJ is a fork of. You can still compile to legacy target versions as low as Java 1.3 when compiling plain - Java code or using plain Java ITD constructs which do not require the AspectJ runtime <tt>aspectjrt</tt>, but the compiler - itself needs JDK 11+. Just like in previous AspectJ versions, both the runtime <tt>aspectjrt</tt> and the load-time weaver - <tt>aspectjweaver</tt> still only require JRE 8+. + The AspectJ compiler <tt>ajc</tt> (contained in the <tt>aspectjtools</tt> library) no longer works on JDKs 8 to 10. + The minimum compile-time requirement is now JDK 11 due to upstream changes in the Eclipse Java Compiler (subset of + JDT Core), which AspectJ is a fork of. You can still compile to legacy target versions as low as Java 1.3 when + compiling plain Java code or using plain Java ITD constructs which do not require the AspectJ runtime + <tt>aspectjrt</tt>, but the compiler itself needs JDK 11+. Just like in previous AspectJ versions, both the runtime + <tt>aspectjrt</tt> and the load-time weaver <tt>aspectjweaver</tt> still only require JRE 8+. </li> <li>Document build profiles and properties in <i>docs/developer/BUILD.md</i></li> <li>Add a guide for setting up an AspectJ development environment in <i>docs/developer/IDE.md</i></li> @@ -104,6 +104,16 @@ aspect library via <tt>-aspectpath</tt> in combination with introducing an annotation via ITD. This was broken since version 1.9.5 and fixed in 1.9.8.RC3. </li> + <li> + Fix <a href="https://github.com/eclipse/org.aspectj/issues/68">issue #68</a>: Correctly process class files + containing <a href="https://openjdk.java.net/jeps/309">dynamic class-file constants (JEP 309)</a>, which were + introduced in Java 11 and broken in AspectJ ever since their introduction in 1.9.2. Java itself currently does not + use "condy" and neither do other widespread JVM languages. Byte code engineering libraries like ASM or Byte Buddy + and some instrumentation tools like JaCoCo can however produce condy code. Therefore, in order to create a + regression test, we actually had to + <a href="https://github.com/eclipse/org.aspectj/blob/de63b63d/tests/bugs198/github_68/Generator.java#L50-L61"> + craft a condy class with ASM</a>. + </li> </ul> <p> 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 <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(); + } + +} 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 Binary files differnew file mode 100644 index 000000000..75fe7e5b8 --- /dev/null +++ b/tests/bugs198/github_68/condy.jar diff --git a/tests/src/test/java/org/aspectj/systemtest/ajc198/AllTestsAspectJ198.java b/tests/src/test/java/org/aspectj/systemtest/ajc198/AllTestsAspectJ198.java index 4aac84810..3cfc7a149 100644 --- a/tests/src/test/java/org/aspectj/systemtest/ajc198/AllTestsAspectJ198.java +++ b/tests/src/test/java/org/aspectj/systemtest/ajc198/AllTestsAspectJ198.java @@ -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()); diff --git a/tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Java11Tests.java b/tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Java11Tests.java new file mode 100644 index 000000000..7e99b7d9f --- /dev/null +++ b/tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Java11Tests.java @@ -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"); + } + +} diff --git a/tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml b/tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml index dfe86e2a9..202258c94 100644 --- a/tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml +++ b/tests/src/test/resources/org/aspectj/systemtest/ajc198/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"/> |