From e4310660ef2e43e88be4e8738b3c4c39f1f582e1 Mon Sep 17 00:00:00 2001 From: Rafael Winterhalter Date: Sat, 11 Aug 2018 15:02:39 +0200 Subject: [PATCH] Add javadoc. --- .../description/type/TypeDescription.java | 130 ++++++++++++++---- .../dynamic/scaffold/InstrumentedType.java | 8 ++ .../java/net/bytebuddy/pool/TypePool.java | 49 +++++++ .../type/AbstractTypeDescriptionTest.java | 9 ++ .../scaffold/InstrumentedTypeDefaultTest.java | 2 +- .../MethodGraphCompilerDefaultTest.java | 4 +- .../TypeWriterModifierPreservationTest.java | 4 +- 7 files changed, 176 insertions(+), 30 deletions(-) diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeDescription.java b/byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeDescription.java index 69d8fdb061e..ad3d3c2261d 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeDescription.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/description/type/TypeDescription.java @@ -332,12 +332,35 @@ public interface TypeDescription extends TypeDefinition, ByteCodeElement, TypeVa */ Object getDefaultValue(); + /** + * Returns the nest host of this type. For types prior to Java 11, this type is returned which is the default nest host. + * + * @return The nest host of this type. + */ TypeDescription getNestHost(); + /** + * Returns a list of members that are part of a nesting group. Prior to Java 11, a list that only contains this type is returned which is + * the default nest group. + * + * @return A list of members of this nest group. + */ TypeList getNestMembers(); + /** + * Checks if this type and the supplied type are members of the same nest group. + * + * @param type The type for which to check if it is a member of the same nest group. + * @return {@code true} if this type and the supplied type are members of the same nest group. + */ boolean isNestMateOf(Class type); + /** + * Checks if this type and the supplied type are members of the same nest group. + * + * @param typeDescription The type for which to check if it is a member of the same nest group. + * @return {@code true} if this type and the supplied type are members of the same nest group. + */ boolean isNestMateOf(TypeDescription typeDescription); /** @@ -7180,6 +7203,9 @@ class ForLoadedType extends AbstractBase implements Serializable { */ private static final long serialVersionUID = 1L; + /** + * A dispatcher for invking methods on {@link Class} reflectively. + */ private static final Dispatcher DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE); /** @@ -7510,75 +7536,129 @@ public TypeList getNestMembers() { @Override public boolean isNestMateOf(Class type) { - return DISPATCHER.isNestmateOf(this.type, type) || super.isNestMateOf(type); + return DISPATCHER.isNestmateOf(this.type, type) || super.isNestMateOf(ForLoadedType.of(type)); } + @Override + public boolean isNestMateOf(TypeDescription typeDescription) { + return typeDescription instanceof ForLoadedType && DISPATCHER.isNestmateOf(type, ((ForLoadedType) typeDescription).type) || super.isNestMateOf(typeDescription); + } + + /** + * A dispatcher for using methods of {@link Class} that are not declared for Java 6. + */ protected interface Dispatcher { - Class getNestHost(Class self); + /** + * Returns the specified class's nest host. + * + * @param type The class for which to locate the nest host. + * @return The nest host of the specified class. + */ + Class getNestHost(Class type); - Class[] getNestMembers(Class self); + /** + * Returns the nest members of the other class. + * + * @param type The type to get the nest members for. + * @return An array containing all nest members of the specified type's nest group. + */ + Class[] getNestMembers(Class type); - boolean isNestmateOf(Class self, Class type); + /** + * Returns {@code true} if the specified type is a nest mate of the other type. + * + * @param type The type to evaluate for being a nest mate of another type. + * @param candidate The candidate type. + * @return {@code true} if the specified type is a nest mate of the other class. + */ + boolean isNestmateOf(Class type, Class candidate); + /** + * An action to resolve the dispatcher for invoking methods of {@link Class} reflectively. + */ enum CreationAction implements PrivilegedAction { + /** + * The singleton instance. + */ INSTANCE; @Override public Dispatcher run() { try { - return ForJava11CapableVm.make(); + return new ForJava11CapableVm(Class.class.getMethod("getNestHost"), + Class.class.getMethod("getNestMembers"), + Class.class.getMethod("isNestmateOf", Class.class)); } catch (NoSuchMethodException ignored) { - return Disabled.INSTANCE; + return ForLegacyVm.INSTANCE; } } } - enum Disabled implements Dispatcher { + /** + * A dispatcher for a legacy VM. + */ + enum ForLegacyVm implements Dispatcher { + /** + * The singleton instance. + */ INSTANCE; @Override - public Class getNestHost(Class self) { - return self; + public Class getNestHost(Class type) { + return type; } @Override - public Class[] getNestMembers(Class self) { - return new Class[]{self}; + public Class[] getNestMembers(Class type) { + return new Class[]{type}; } @Override - public boolean isNestmateOf(Class self, Class type) { - return self == type; + public boolean isNestmateOf(Class type, Class candidate) { + return type == candidate; } } + /** + * A dispatcher for a Java 11-capable VM. + */ class ForJava11CapableVm implements Dispatcher { + /** + * The {@code java.lang.Class#getNestHost} method. + */ private final Method getNestHost; + /** + * The {@code java.lang.Class#getNestMembers} method. + */ private final Method getNestMembers; + /** + * The {@code java.lang.Class#isNestmateOf} method. + */ private final Method isNestmateOf; + /** + * Creates a dispatcher for a Java 11-capable VM. + * + * @param getNestHost The {@code java.lang.Class#getNestHost} method. + * @param getNestMembers The {@code java.lang.Class#getNestMembers} method. + * @param isNestmateOf The {@code java.lang.Class#isNestmateOf} method. + */ protected ForJava11CapableVm(Method getNestHost, Method getNestMembers, Method isNestmateOf) { this.getNestHost = getNestHost; this.getNestMembers = getNestMembers; this.isNestmateOf = isNestmateOf; } - protected static Dispatcher make() throws NoSuchMethodException { - return new ForJava11CapableVm(Class.class.getMethod("getNestHost"), - Class.class.getMethod("getNestMembers"), - Class.class.getMethod("isNestmateOf", Class.class)); - } - @Override - public Class getNestHost(Class self) { + public Class getNestHost(Class type) { try { - return (Class) getNestHost.invoke(self); + return (Class) getNestHost.invoke(type); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access Class::getNestHost", exception); } catch (InvocationTargetException exception) { @@ -7587,9 +7667,9 @@ public Class getNestHost(Class self) { } @Override - public Class[] getNestMembers(Class self) { + public Class[] getNestMembers(Class type) { try { - return (Class[]) getNestMembers.invoke(self); + return (Class[]) getNestMembers.invoke(type); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access Class::getNestMembers", exception); } catch (InvocationTargetException exception) { @@ -7598,9 +7678,9 @@ public Class[] getNestMembers(Class self) { } @Override - public boolean isNestmateOf(Class self, Class type) { + public boolean isNestmateOf(Class type, Class candidate) { try { - return (Boolean) isNestmateOf.invoke(self, type); + return (Boolean) isNestmateOf.invoke(type, candidate); } catch (IllegalAccessException exception) { throw new IllegalStateException("Could not access Class::isNestmateOf", exception); } catch (InvocationTargetException exception) { diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/InstrumentedType.java b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/InstrumentedType.java index 6595ac9c86b..cf27472126f 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/InstrumentedType.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/InstrumentedType.java @@ -376,8 +376,14 @@ class Default extends AbstractBase.OfSimpleType implements InstrumentedType.With */ private final boolean localClass; + /** + * The nest host of this instrumented type or a description of {@link TargetType} if this type is its own nest host. + */ private final TypeDescription nestHost; + /** + * A list of all members of this types nest group excluding this type. + */ private final List nestMembers; /** @@ -400,6 +406,8 @@ class Default extends AbstractBase.OfSimpleType implements InstrumentedType.With * @param memberClass {@code true} if this type is a member class. * @param anonymousClass {@code true} if this type is a anonymous class. * @param localClass {@code true} if this type is a local class. + * @param nestHost The nest host of this instrumented type or a description of {@link TargetType} if this type is its own nest host. + * @param nestMembers A list of all members of this types nest group excluding this type. */ protected Default(String name, int modifiers, diff --git a/byte-buddy-dep/src/main/java/net/bytebuddy/pool/TypePool.java b/byte-buddy-dep/src/main/java/net/bytebuddy/pool/TypePool.java index 3c7da5c9f16..53c77cebe8a 100644 --- a/byte-buddy-dep/src/main/java/net/bytebuddy/pool/TypePool.java +++ b/byte-buddy-dep/src/main/java/net/bytebuddy/pool/TypePool.java @@ -2587,8 +2587,14 @@ protected static class LazyTypeDescription extends TypeDescription.AbstractBase. */ private final boolean anonymousType; + /** + * The binary name of the nest host or {@code null} if no nest host was specified. + */ private final String nestHost; + /** + * A list of binary names of all specified nest members. + */ private final List nestMembers; /** @@ -2635,6 +2641,8 @@ protected static class LazyTypeDescription extends TypeDescription.AbstractBase. * @param declaringTypeInternalName The internal name of this type's declaring type or {@code null} if no such type exists. * @param declaredTypes A list of descriptors representing the types that are declared by this type. * @param anonymousType {@code true} if this type is an anonymous type. + * @param nestHostInternalName The internal name of the nest host or {@code null} if no nest host was specified. + * @param nestMemberInternalNames A list of internal names of the nest members. * @param superTypeAnnotationTokens A mapping of type annotations for this type's super type and interface types by their indices. * @param typeVariableAnnotationTokens A mapping of type annotations of the type variables' type annotations by their indices. * @param typeVariableBoundsAnnotationTokens A mapping of type annotations of the type variables' bounds' type annotations by their indices @@ -5778,14 +5786,33 @@ public int getStackSize() { } } + /** + * A lazy list that represents all nest members of the represented type. + */ protected static class LazyNestMemberList extends TypeList.AbstractBase { + /** + * The type for which the nest members are represented. + */ private final TypeDescription typeDescription; + /** + * The type pool to use for looking up types. + */ private final TypePool typePool; + /** + * The binary names of all nest members of this nest mate group excluding the represented type. + */ private final List nestMembers; + /** + * Creates a new lazy type list of all nest members of this group. + * + * @param typeDescription The type for which the nest members are represented. + * @param typePool The type pool to use for looking up types. + * @param nestMembers The binary names of all nest members of this nest mate group excluding the represented type. + */ protected LazyNestMemberList(TypeDescription typeDescription, TypePool typePool, List nestMembers) { this.typeDescription = typeDescription; this.typePool = typePool; @@ -5803,6 +5830,22 @@ public TypeDescription get(int index) { public int size() { return nestMembers.size() + 1; } + + @Override + public String[] toInternalNames() { + String[] internalName = new String[nestMembers.size() + 1]; + internalName[0] = typeDescription.getInternalName(); + int index = 1; + for (String name : nestMembers) { + internalName[index++] = name.replace('.', '/'); + } + return internalName; + } + + @Override + public int getStackSize() { + return nestMembers.size() + 1; + } } /** @@ -6849,8 +6892,14 @@ protected class TypeExtractor extends ClassVisitor { */ private boolean anonymousType; + /** + * The nest host that was found in the class file or {@code null} if no nest host was specified. + */ private String nestHost; + /** + * A list of nest members that were found in the class file. + */ private final List nestMembers; /** diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/AbstractTypeDescriptionTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/AbstractTypeDescriptionTest.java index 5c60d6c4537..29cc0de4872 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/AbstractTypeDescriptionTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/description/type/AbstractTypeDescriptionTest.java @@ -679,6 +679,15 @@ public void testUnboxed() throws Exception { assertThat(describe(Object.class).asUnboxed(), is(describe(Object.class))); } + @Test + public void testNestMatesPreJava() { + assertThat(describe(Object.class).getNestHost(), is(TypeDescription.OBJECT)); + assertThat(describe(Object.class).getNestMembers().size(), is(1)); + assertThat(describe(Object.class).getNestMembers(), hasItem(TypeDescription.OBJECT)); + assertThat(describe(Object.class).isNestMateOf(Object.class), is(true)); + assertThat(describe(Object.class).isNestMateOf(TypeDescription.STRING), is(false)); + } + private Class inMethodClass() { class InMethod { /* empty */ diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/InstrumentedTypeDefaultTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/InstrumentedTypeDefaultTest.java index c54d613dc01..645c2701929 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/InstrumentedTypeDefaultTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/InstrumentedTypeDefaultTest.java @@ -1275,7 +1275,7 @@ public void testTypeVariableOutOfScopeIsErased() throws Exception { false, false, TargetType.DESCRIPTION, - Collections.singletonList(TargetType.DESCRIPTION)); + Collections.emptyList()); MethodDescription methodDescription = typeDescription.getSuperClass().getSuperClass().getDeclaredMethods().filter(named(FOO)).getOnly(); assertThat(methodDescription.getReturnType(), is(TypeDescription.Generic.OBJECT)); } diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/MethodGraphCompilerDefaultTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/MethodGraphCompilerDefaultTest.java index 32f497ef312..9b1a7378e5c 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/MethodGraphCompilerDefaultTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/MethodGraphCompilerDefaultTest.java @@ -1058,7 +1058,7 @@ public void testVisibilityExtension() throws Exception { false, false, TargetType.DESCRIPTION, - Collections.singletonList(TargetType.DESCRIPTION)); + Collections.emptyList()); MethodDescription.SignatureToken signatureToken = new MethodDescription.SignatureToken("foo", TypeDescription.ForLoadedType.of(void.class), Collections.emptyList()); @@ -1098,7 +1098,7 @@ public void testOrphanedBridge() throws Exception { false, false, TargetType.DESCRIPTION, - Collections.singletonList(TargetType.DESCRIPTION)); + Collections.emptyList()); MethodGraph.Linked methodGraph = MethodGraph.Compiler.Default.forJavaHierarchy().compile(typeDescription); assertThat(methodGraph.listNodes().size(), is(1 + TypeDescription.OBJECT.getDeclaredMethods().filter(ElementMatchers.isVirtual()).size())); MethodGraph.Node node = methodGraph.locate(bridgeMethod); diff --git a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterModifierPreservationTest.java b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterModifierPreservationTest.java index 0601bbd38fe..78c8f68c05e 100644 --- a/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterModifierPreservationTest.java +++ b/byte-buddy-dep/src/test/java/net/bytebuddy/dynamic/scaffold/TypeWriterModifierPreservationTest.java @@ -72,7 +72,7 @@ private static class TypeModifierExtractor extends ClassVisitor { public int modifiers, inner; - public TypeModifierExtractor() { + private TypeModifierExtractor() { super(OpenedClassReader.ASM_API); } @@ -96,7 +96,7 @@ private static class TypeValidator extends ClassVisitor { public final int modifiers, inner; - public TypeValidator(ClassVisitor classVisitor, int modifiers, int inner) { + private TypeValidator(ClassVisitor classVisitor, int modifiers, int inner) { super(OpenedClassReader.ASM_API, classVisitor); this.modifiers = modifiers; this.inner = inner;