diff --git a/byte-buddy-dep/pom.xml b/byte-buddy-dep/pom.xml index 3896284879..aad5b6f91a 100644 --- a/byte-buddy-dep/pom.xml +++ b/byte-buddy-dep/pom.xml @@ -382,6 +382,29 @@ + + org.apache.maven.plugins + maven-resources-plugin + ${version.plugin.resources} + + + copy-advice-templates + + copy-resources + + prepare-package + + ${basedir}/target/destination-folder + + + src/main/precompiled-6 + false + + + + + + @@ -593,18 +616,6 @@ build-helper-maven-plugin ${version.plugin.buildhelper} - - java-6-precompile - generate-sources - - add-source - - - - src/main/java-6 - - - java-6-precompile-test generate-sources @@ -624,20 +635,6 @@ maven-antrun-plugin ${version.plugin.antrun} - - java-6-precompile-copy - process-classes - - run - - - - - - - - - java-6-precompile-test-copy process-test-classes @@ -666,11 +663,6 @@ - - - src/main/precompiled-6 - - src/test/precompiled-6 diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$Object.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$Object.java deleted file mode 100644 index 23bfb00802..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$Object.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; -import net.bytebuddy.implementation.bytecode.assign.Assigner; - -/** - * An advice class for caching a reference value. - */ -class CachedReturnPlugin$Advice$Object { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$Object() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static Object enter(@CachedReturnPlugin.CacheField Object cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object returned, @CachedReturnPlugin.CacheField Object cached) { - if (returned == null) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$boolean.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$boolean.java deleted file mode 100644 index 34fe87599f..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$boolean.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code boolean} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$boolean { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$boolean() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static boolean enter(@CachedReturnPlugin.CacheField boolean cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) boolean returned, @CachedReturnPlugin.CacheField boolean cached) { - if (returned) { - cached = true; - } else { - returned = true; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$byte.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$byte.java deleted file mode 100644 index 99aa7de9f5..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$byte.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code byte} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$byte { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$byte() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static byte enter(@CachedReturnPlugin.CacheField byte cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) byte returned, @CachedReturnPlugin.CacheField byte cached) { - if (returned == 0) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$char.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$char.java deleted file mode 100644 index 55a7f029fe..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$char.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code char} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$char { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$char() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static char enter(@CachedReturnPlugin.CacheField char cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) char returned, @CachedReturnPlugin.CacheField char cached) { - if (returned == 0) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$double.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$double.java deleted file mode 100644 index 07615848a4..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$double.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code double} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$double { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$double() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static double enter(@CachedReturnPlugin.CacheField double cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) double returned, @CachedReturnPlugin.CacheField double cached) { - if (returned == 0d) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$float.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$float.java deleted file mode 100644 index a5d60f8353..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$float.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code float} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$float { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$float() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static float enter(@CachedReturnPlugin.CacheField float cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) float returned, @CachedReturnPlugin.CacheField float cached) { - if (returned == 0f) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$int.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$int.java deleted file mode 100644 index 69ce128110..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$int.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code int} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$int { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$int() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static int enter(@CachedReturnPlugin.CacheField int cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) int returned, @CachedReturnPlugin.CacheField int cached) { - if (returned == 0) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$long.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$long.java deleted file mode 100644 index c05cbaf41a..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$long.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code long} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$long { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$long() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static long enter(@CachedReturnPlugin.CacheField long cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) long returned, @CachedReturnPlugin.CacheField long cached) { - if (returned == 0L) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$short.java b/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$short.java deleted file mode 100644 index c525e124f1..0000000000 --- a/byte-buddy-dep/src/main/java-6/net/bytebuddy/build/CachedReturnPlugin$Advice$short.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2014 - Present Rafael Winterhalter - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.bytebuddy.build; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import net.bytebuddy.asm.Advice; - -/** - * An advice class for caching a {@code short} value. - */ -@SuppressFBWarnings(value = "NM_CLASS_NAMING_CONVENTION", justification = "Name is chosen to optimize for simple lookup") -class CachedReturnPlugin$Advice$short { - - /** - * A constructor that prohibits the instantiation of the class. - */ - private CachedReturnPlugin$Advice$short() { - throw new UnsupportedOperationException("This class is merely an advice template and should not be instantiated"); - } - - /** - * The enter advice. - * - * @param cached The cached field's value. - * @return {@code true} if a cached value exists. - */ - @Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class) - protected static short enter(@CachedReturnPlugin.CacheField short cached) { - return cached; - } - - /** - * The exit advice. - * - * @param returned The value that was returned by the method's execution or {@code 0} if it was not executed. - * @param cached The previously cached value or {@code 0} if no previous value exists. - */ - @Advice.OnMethodExit - @SuppressFBWarnings(value = {"UC_USELESS_VOID_METHOD", "DLS_DEAD_LOCAL_STORE"}, justification = "Advice method serves as a template") - protected static void exit(@Advice.Return(readOnly = false) short returned, @CachedReturnPlugin.CacheField short cached) { - if (returned == 0) { - returned = cached; - } else { - cached = returned; - } - } -} diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/build/CachedReturnPlugin.java b/byte-buddy-dep/src/main/java/net/bytebuddy/build/CachedReturnPlugin.java index d3ae6c1392..37f6201f03 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/build/CachedReturnPlugin.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/build/CachedReturnPlugin.java @@ -16,22 +16,33 @@ package net.bytebuddy.build; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import net.bytebuddy.ByteBuddy; +import net.bytebuddy.ClassFileVersion; import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.annotation.AnnotationDescription; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.modifier.FieldPersistence; import net.bytebuddy.description.modifier.Ownership; import net.bytebuddy.description.modifier.SyntheticState; import net.bytebuddy.description.modifier.Visibility; +import net.bytebuddy.description.type.TypeDefinition; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.ClassFileLocator; import net.bytebuddy.dynamic.DynamicType; +import net.bytebuddy.dynamic.scaffold.TypeValidation; +import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy; +import net.bytebuddy.implementation.Implementation; +import net.bytebuddy.implementation.bytecode.ByteCodeAppender; +import net.bytebuddy.implementation.bytecode.StackSize; import net.bytebuddy.implementation.bytecode.assign.Assigner; -import net.bytebuddy.pool.TypePool; +import net.bytebuddy.implementation.bytecode.member.MethodReturn; +import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess; import net.bytebuddy.utility.RandomString; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import java.lang.annotation.*; -import java.util.HashMap; -import java.util.Map; import static net.bytebuddy.matcher.ElementMatchers.*; @@ -51,11 +62,6 @@ public class CachedReturnPlugin extends Plugin.ForElementMatcher implements Plug */ private static final String NAME_INFIX = "_"; - /** - * The infix symbol for advice classes. - */ - private static final String ADVICE_INFIX = "$Advice$"; - /** * A description of the {@link Enhance#value()} method. */ @@ -75,21 +81,6 @@ public class CachedReturnPlugin extends Plugin.ForElementMatcher implements Plug @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.IGNORE) private final RandomString randomString; - /** - * The class file locator to use. - */ - private final ClassFileLocator classFileLocator; - - /** - * A map of advice types mapped by their argument type. All advice types are precompiled using Java 6 to allow - * for releasing Byte Buddy with a Java 5 byte code level where compiled classes do not contain stack map frames. - * Byte Buddy filters stack map frames when applying advice in newer version but it cannot add stack map frames - * without explicit frame computation which is expensive which is why precompilation was used. To avoid loading - * Java classes in incompatible versions, all advice types are resolved using a type pool. - */ - @HashCodeAndEqualsPlugin.ValueHandling(HashCodeAndEqualsPlugin.ValueHandling.Sort.IGNORE) - private final Map adviceByType; - /** * Creates a plugin for caching method return values. If a field name exists before applying this plugin, an exception is raised. */ @@ -106,24 +97,6 @@ public CachedReturnPlugin(boolean ignoreExistingFields) { super(declaresMethod(isAnnotatedWith(Enhance.class))); this.ignoreExistingFields = ignoreExistingFields; randomString = new RandomString(); - classFileLocator = ClassFileLocator.ForClassLoader.of(CachedReturnPlugin.class.getClassLoader()); - TypePool typePool = TypePool.Default.of(classFileLocator); - adviceByType = new HashMap(); - for (Class type : new Class[]{ - boolean.class, - byte.class, - short.class, - char.class, - int.class, - long.class, - float.class, - double.class, - Object.class - }) { - adviceByType.put(TypeDescription.ForLoadedType.ForLoadedType.of(type), typePool.describe(CachedReturnPlugin.class.getName() - + ADVICE_INFIX - + type.getSimpleName()).resolve()); - } } /** @@ -161,12 +134,9 @@ public DynamicType.Builder apply(DynamicType.Builder builder, TypeDescript : Ownership.MEMBER, methodDescription.isStatic() ? FieldPersistence.PLAIN : FieldPersistence.TRANSIENT, Visibility.PRIVATE, SyntheticState.SYNTHETIC) - .visit(Advice.withCustomMapping() - .bind(CacheField.class, new CacheFieldOffsetMapping(name)) - .to(adviceByType.get(methodDescription.getReturnType().isPrimitive() - ? methodDescription.getReturnType().asErasure() - : TypeDescription.ForLoadedType.of(Object.class)), this.classFileLocator) - .on(is(methodDescription))); + .visit(AdviceResolver + .of(methodDescription.getReturnType()) + .toAdvice(name).on(is(methodDescription))); } return builder; } @@ -205,6 +175,215 @@ public void close() { /* empty */ } + /** + * A resolver for {@link Advice} that caches a method's return type. + */ + protected enum AdviceResolver { + + /** + * A resolver for a {@code boolean} type. + */ + BOOLEAN(boolean.class, Opcodes.ILOAD, Opcodes.ISTORE, Opcodes.NOP, Opcodes.IFNE), + + /** + * A resolver for a {@code byte} type. + */ + BYTE(byte.class, Opcodes.ILOAD, Opcodes.ISTORE, Opcodes.NOP, Opcodes.IFNE), + + /** + * A resolver for a {@code short} type. + */ + SHORT(short.class, Opcodes.ILOAD, Opcodes.ISTORE, Opcodes.NOP, Opcodes.IFNE), + + /** + * A resolver for a {@code char} type. + */ + CHARACTER(char.class, Opcodes.ILOAD, Opcodes.ISTORE, Opcodes.NOP, Opcodes.IFNE), + + /** + * A resolver for a {@code int} type. + */ + INTEGER(int.class, Opcodes.ILOAD, Opcodes.ISTORE, Opcodes.NOP, Opcodes.IFNE), + + /** + * A resolver for a {@code long} type. + */ + LONG(long.class, Opcodes.LLOAD, Opcodes.LSTORE, Opcodes.L2I, Opcodes.IFNE), + + /** + * A resolver for a {@code float} type. + */ + FLOAT(float.class, Opcodes.FLOAD, Opcodes.FSTORE, Opcodes.F2I, Opcodes.IFNE), + + /** + * A resolver for a {@code double} type. + */ + DOUBLE(double.class, Opcodes.DLOAD, Opcodes.DSTORE, Opcodes.D2I, Opcodes.IFNE), + + /** + * A resolver for a reference type. + */ + REFERENCE(Object.class, Opcodes.ALOAD, Opcodes.ASTORE, Opcodes.NOP, Opcodes.IFNONNULL); + + /** + * The created dynamic type to use for advice. + */ + private final DynamicType.Loaded dynamicType; + + /** + * Creates an advice resolver. + * + * @param type The type of the return type. + * @param load The byte code that loads a value onto the stack from the local variable array. + * @param store The byte code that stores a value to the local variable array. + * @param convert An instruction to convert the cached value to a value that is applied on the branch instruction. + * @param branch A jump instruction that checks if the cached value is already set. + */ + AdviceResolver(Class type, int load, int store, int convert, int branch) { + dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V6) + .with(TypeValidation.DISABLED) + .subclass(Object.class, ConstructorStrategy.Default.NO_CONSTRUCTORS) + .name(CachedReturnPlugin.class.getName() + "$Advice$" + this) + .defineMethod("enter", type, Ownership.STATIC) + .withParameter(type) + .annotateParameter(AnnotationDescription.Builder.ofType(CachedReturnPlugin.CacheField.class).build()) + .intercept(new Implementation.Simple( + MethodVariableAccess.of(TypeDescription.ForLoadedType.of(type)).loadFrom(0), + MethodReturn.of(TypeDescription.ForLoadedType.of(type)) + )) + .annotateMethod(AnnotationDescription.Builder.ofType(Advice.OnMethodEnter.class) + .define("skipOn", Advice.OnNonDefaultValue.class) + .build()) + .defineMethod("exit", void.class, Ownership.STATIC) + .withParameter(type) + .annotateParameter(AnnotationDescription.Builder.ofType(Advice.Return.class) + .define("readOnly", false) + .define("typing", Assigner.Typing.DYNAMIC) + .build()) + .withParameter(type) + .annotateParameter(AnnotationDescription.Builder.ofType(CachedReturnPlugin.CacheField.class).build()) + .intercept(new Implementation.Simple(new ExitAdviceByteCodeAppender(load, store, convert, branch, StackSize.of(type).getSize()))) + .annotateMethod(AnnotationDescription.Builder.ofType(Advice.OnMethodExit.class).build()) + .make() + .load(null); + dynamicType.getLoaded().getMethods(); + } + + /** + * Creates an advice resolver for a given type definition. + * + * @param typeDefinition The type definition for which advice is to be created. + * @return An appropriate advice resolver. + */ + protected static AdviceResolver of(TypeDefinition typeDefinition) { + if (typeDefinition.represents(boolean.class)) { + return BOOLEAN; + } else if (typeDefinition.represents(byte.class)) { + return BYTE; + } else if (typeDefinition.represents(short.class)) { + return SHORT; + } else if (typeDefinition.represents(char.class)) { + return CHARACTER; + } else if (typeDefinition.represents(int.class)) { + return INTEGER; + } else if (typeDefinition.represents(long.class)) { + return LONG; + } else if (typeDefinition.represents(float.class)) { + return FLOAT; + } else if (typeDefinition.represents(double.class)) { + return DOUBLE; + } else if (typeDefinition.isPrimitive()) { + throw new IllegalArgumentException("Unexpected advice type: " + typeDefinition); + } else { + return REFERENCE; + } + } + + /** + * Resolve advice for a given field name. + * + * @param name The name of the field to resolve the advice for. + * @return An appropriate advice. + */ + protected Advice toAdvice(String name) { + return Advice.withCustomMapping() + .bind(CacheField.class, new CacheFieldOffsetMapping(name)) + .to(dynamicType.getTypeDescription(), dynamicType); + } + + /** + * A byte code appender for the exit advice. + */ + @HashCodeAndEqualsPlugin.Enhance + protected static class ExitAdviceByteCodeAppender implements ByteCodeAppender { + + /** + * The byte code that loads a value onto the stack from the local variable array. + */ + private final int load; + + /** + * The byte code that stores a value to the local variable array. + */ + private final int store; + + /** + * An instruction to convert the cached value to a value that is applied on the branch instruction. + */ + private final int convert; + + /** + * A jump instruction that checks if the cached value is already set. + */ + private final int branch; + + /** + * The size of the created type on the operand stack. + */ + private final int size; + + /** + * Creates a byte code appender for exit advice on a cached return plugin. + * + * @param load The byte code that loads a value onto the stack from the local variable array. + * @param store The byte code that stores a value to the local variable array. + * @param convert An instruction to convert the cached value to a value that is applied on the branch instruction. + * @param branch A jump instruction that checks if the cached value is already set. + * @param size The size of the created type on the operand stack. + */ + protected ExitAdviceByteCodeAppender(int load, int store, int convert, int branch, int size) { + this.load = load; + this.store = store; + this.convert = convert; + this.branch = branch; + this.size = size; + } + + /** + * {@inheritDoc} + */ + public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext, MethodDescription instrumentedMethod) { + Label complete = new Label(), uncached = new Label(); + methodVisitor.visitVarInsn(load, 0); + if (convert != Opcodes.NOP) { + methodVisitor.visitInsn(convert); + } + methodVisitor.visitJumpInsn(branch, uncached); + methodVisitor.visitVarInsn(load, size); + methodVisitor.visitVarInsn(store, 0); + methodVisitor.visitJumpInsn(Opcodes.GOTO, complete); + methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + methodVisitor.visitLabel(uncached); + methodVisitor.visitVarInsn(load, 0); + methodVisitor.visitVarInsn(store, size); + methodVisitor.visitLabel(complete); + methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + methodVisitor.visitInsn(Opcodes.RETURN); + return new Size(size * 2, instrumentedMethod.getStackSize()); + } + } + } + /** * An offset mapping for the cached field. */ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$Object.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$Object.class deleted file mode 100644 index 0c2c809e48..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$Object.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$boolean.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$boolean.class deleted file mode 100644 index 84c9ce0f57..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$boolean.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$byte.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$byte.class deleted file mode 100644 index cbf3d68c97..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$byte.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$char.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$char.class deleted file mode 100644 index 959fc8d9ed..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$char.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$double.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$double.class deleted file mode 100644 index 17f3be01e2..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$double.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$float.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$float.class deleted file mode 100644 index 71674352e4..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$float.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$int.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$int.class deleted file mode 100644 index 9be9616ae5..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$int.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$long.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$long.class deleted file mode 100644 index 98e42c0414..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$long.class and /dev/null differ diff --git a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$short.class b/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$short.class deleted file mode 100644 index 83bbbb904b..0000000000 Binary files a/byte-buddy-dep/src/main/precompiled-6/net/bytebuddy/build/CachedReturnPlugin$Advice$short.class and /dev/null differ diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginOtherTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginOtherTest.java index 19b4e9144e..6518035979 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginOtherTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginOtherTest.java @@ -1,6 +1,7 @@ package net.bytebuddy.build; import net.bytebuddy.ByteBuddy; +import net.bytebuddy.description.type.TypeDefinition; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.ClassFileLocator; import net.bytebuddy.dynamic.DynamicType; @@ -42,6 +43,11 @@ public void testParameterMethod() { ClassFileLocator.ForClassLoader.of(ParameterCache.class.getClassLoader())); } + @Test(expected = IllegalArgumentException.class) + public void testAdviceResolverVoid() { + CachedReturnPlugin.AdviceResolver.of(TypeDescription.ForLoadedType.of(void.class)); + } + private static class VoidCache { @CachedReturnPlugin.Enhance diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginTest.java index 1581d3d15a..cd1536fa37 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/build/CachedReturnPluginTest.java @@ -77,26 +77,6 @@ public void testCachedValue() throws Exception { assertThat(transformed.getMethod(FOO).invoke(instance), is(value)); } - @Test(expected = UnsupportedOperationException.class) - public void testCannotConstructAdvice() throws Exception { - Constructor constructor = Class.forName(CachedReturnPlugin.class.getName() + "$Advice$" + adviceArgument.getSimpleName(), - true, - CachedReturnPlugin.class.getClassLoader()).getDeclaredConstructor(); - constructor.setAccessible(true); - try { - constructor.newInstance(); - fail(); - } catch (InvocationTargetException exception) { - throw (Exception) exception.getTargetException(); - } - } - - @Test - public void testJavaVersion() throws Exception { - Class type = Class.forName(CachedReturnPlugin.class.getName() + "$Advice$" + adviceArgument.getSimpleName()); - assertThat(ClassFileVersion.of(type), is(ClassFileVersion.JAVA_V6)); - } - public static class BooleanSample { private boolean executed;