Deprecate RuntimeHintsAgent Java agent

This Java agent has been designed to instrument specific JDK calls for
reflective introspection and invocations. This is useful for testing
runtime hints in integration tests.

As of GraalVM 23, there is a new VM option that does this in a much more
efficient and precise fashion. Developers can use the
`-XX:MissingRegistrationReportingMode` with the "Warn" or "Exit" value.
The option will look for reachability metadata and emit logs in "Warn"
mode or immediately exit the application with in "Exit" mode.

This commit deprecates the `RuntimeHintsAgent` in favor of this new,
more reliable option.

See gh-33847
This commit is contained in:
Brian Clozel 2024-11-29 14:44:02 +01:00
parent 71362c953c
commit 0759129c14
4 changed files with 80 additions and 291 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,13 +20,11 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ResourceBundle;
import java.util.function.Function;
import java.util.function.Predicate;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
@ -67,8 +65,7 @@ enum InstrumentedMethod {
CLASS_GETCLASSES(Class.class, "getClasses", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass))
.withAnyMemberCategory(MemberCategory.DECLARED_CLASSES, MemberCategory.PUBLIC_CLASSES);
return reflection().onType(TypeReference.of(thisClass));
}
),
@ -81,7 +78,7 @@ enum InstrumentedMethod {
if (constructor == null) {
return runtimeHints -> false;
}
return reflection().onConstructor(constructor).introspect();
return reflection().onType(constructor.getDeclaringClass());
}
),
@ -91,9 +88,7 @@ enum InstrumentedMethod {
CLASS_GETCONSTRUCTORS(Class.class, "getConstructors", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass)).withAnyMemberCategory(
MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
return reflection().onType(TypeReference.of(thisClass));
}
),
@ -103,7 +98,7 @@ enum InstrumentedMethod {
CLASS_GETDECLAREDCLASSES(Class.class, "getDeclaredClasses", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass)).withMemberCategory(MemberCategory.DECLARED_CLASSES);
return reflection().onType(TypeReference.of(thisClass));
}
),
@ -116,9 +111,7 @@ enum InstrumentedMethod {
if (constructor == null) {
return runtimeHints -> false;
}
TypeReference thisType = invocation.getInstanceTypeReference();
return reflection().onType(thisType).withMemberCategory(MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS)
.or(reflection().onConstructor(constructor).introspect());
return reflection().onType(constructor.getDeclaringClass());
}
),
@ -128,8 +121,7 @@ enum InstrumentedMethod {
CLASS_GETDECLAREDCONSTRUCTORS(Class.class, "getDeclaredConstructors", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass))
.withAnyMemberCategory(MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
return reflection().onType(TypeReference.of(thisClass));
}),
/**
@ -141,9 +133,7 @@ enum InstrumentedMethod {
if (field == null) {
return runtimeHints -> false;
}
TypeReference thisType = invocation.getInstanceTypeReference();
return reflection().onType(thisType).withMemberCategory(MemberCategory.DECLARED_FIELDS)
.or(reflection().onField(field));
return reflection().onType(field.getDeclaringClass());
}
),
@ -153,7 +143,7 @@ enum InstrumentedMethod {
CLASS_GETDECLAREDFIELDS(Class.class, "getDeclaredFields", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass)).withMemberCategory(MemberCategory.DECLARED_FIELDS);
return reflection().onType(TypeReference.of(thisClass));
}
),
@ -166,10 +156,7 @@ enum InstrumentedMethod {
if (method == null) {
return runtimeHints -> false;
}
TypeReference thisType = invocation.getInstanceTypeReference();
return reflection().onType(thisType)
.withAnyMemberCategory(MemberCategory.INTROSPECT_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_METHODS)
.or(reflection().onMethod(method).introspect());
return reflection().onType(method.getDeclaringClass());
}
),
@ -179,8 +166,7 @@ enum InstrumentedMethod {
CLASS_GETDECLAREDMETHODS(Class.class, "getDeclaredMethods", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass))
.withAnyMemberCategory(MemberCategory.INTROSPECT_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_METHODS);
return reflection().onType(TypeReference.of(thisClass));
}
),
@ -194,10 +180,7 @@ enum InstrumentedMethod {
if (field == null) {
return runtimeHints -> false;
}
TypeReference thisType = invocation.getInstanceTypeReference();
return reflection().onType(thisType).withMemberCategory(MemberCategory.PUBLIC_FIELDS)
.and(runtimeHints -> Modifier.isPublic(field.getModifiers()))
.or(reflection().onType(thisType).withMemberCategory(MemberCategory.DECLARED_FIELDS))
return reflection().onType(field.getDeclaringClass())
.or(reflection().onField(invocation.getReturnValue()));
}),
@ -207,8 +190,7 @@ enum InstrumentedMethod {
CLASS_GETFIELDS(Class.class, "getFields", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass))
.withAnyMemberCategory(MemberCategory.PUBLIC_FIELDS, MemberCategory.DECLARED_FIELDS);
return reflection().onType(TypeReference.of(thisClass));
}
),
@ -221,12 +203,7 @@ enum InstrumentedMethod {
if (method == null) {
return runtimeHints -> false;
}
TypeReference thisType = invocation.getInstanceTypeReference();
return reflection().onType(thisType).withAnyMemberCategory(MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS)
.and(runtimeHints -> Modifier.isPublic(method.getModifiers()))
.or(reflection().onType(thisType).withAnyMemberCategory(MemberCategory.INTROSPECT_DECLARED_METHODS, MemberCategory.INVOKE_DECLARED_METHODS))
.or(reflection().onMethod(method).introspect())
.or(reflection().onMethod(method).invoke());
return reflection().onType(method.getDeclaringClass());
}
),
@ -236,9 +213,7 @@ enum InstrumentedMethod {
CLASS_GETMETHODS(Class.class, "getMethods", HintType.REFLECTION,
invocation -> {
Class<?> thisClass = invocation.getInstance();
return reflection().onType(TypeReference.of(thisClass)).withAnyMemberCategory(
MemberCategory.INTROSPECT_PUBLIC_METHODS, MemberCategory.INTROSPECT_DECLARED_METHODS,
MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_DECLARED_METHODS);
return reflection().onType(TypeReference.of(thisClass));
}
),

View File

@ -39,7 +39,10 @@ import org.springframework.util.StringUtils;
* @author Brian Clozel
* @since 6.0
* @see InvocationsRecorderClassTransformer
* @deprecated as of 7.0 in favor of the {@code -XX:MissingRegistrationReportingMode=Warn} and
* {@code -XX:MissingRegistrationReportingMode=Exit} JVM flags with GraalVM.
*/
@Deprecated(forRemoval = true)
public final class RuntimeHintsAgent {
private static boolean loaded = false;

View File

@ -22,17 +22,20 @@ import java.util.Deque;
import org.springframework.aot.agent.RecordedInvocation;
import org.springframework.aot.agent.RecordedInvocationsListener;
import org.springframework.aot.agent.RecordedInvocationsPublisher;
import org.springframework.aot.agent.RuntimeHintsAgent;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.util.Assert;
/**
* Invocations relevant to {@link RuntimeHints} recorded during the execution of a block
* of code instrumented by the {@link RuntimeHintsAgent}.
* of code instrumented by the {@link org.springframework.aot.agent.RuntimeHintsAgent}.
*
* @author Brian Clozel
* @since 6.0
* @deprecated as of 7.0 in favor of the {@code -XX:MissingRegistrationReportingMode=Warn} and
* {@code -XX:MissingRegistrationReportingMode=Exit} JVM flags with GraalVM.
*/
@Deprecated(forRemoval = true)
@SuppressWarnings("removal")
public final class RuntimeHintsRecorder {
private final RuntimeHintsInvocationsListener listener;
@ -49,7 +52,7 @@ public final class RuntimeHintsRecorder {
*/
public static synchronized RuntimeHintsInvocations record(Runnable action) {
Assert.notNull(action, "Runnable action must not be null");
Assert.state(RuntimeHintsAgent.isLoaded(), "RuntimeHintsAgent must be loaded in the current JVM");
Assert.state(org.springframework.aot.agent.RuntimeHintsAgent.isLoaded(), "RuntimeHintsAgent must be loaded in the current JVM");
RuntimeHintsRecorder recorder = new RuntimeHintsRecorder();
RecordedInvocationsPublisher.addListener(recorder.listener);
try {

View File

@ -61,32 +61,26 @@ class InstrumentedMethodTests {
}
@Test
void classGetClassesShouldNotMatchReflectionOnType() {
void classForNameShouldNotMatchWhenMissingReflectionOnType() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_FORNAME)
.withArgument("java.lang.String").returnValue(String.class).build();
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_FORNAME, invocation);
}
@Test
void classGetClassesShouldMatchReflectionOnType() {
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETCLASSES, this.stringGetClasses);
}
@Test
void classGetClassesShouldMatchPublicClasses() {
hints.reflection().registerType(String.class, MemberCategory.PUBLIC_CLASSES);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCLASSES, this.stringGetClasses);
}
@Test
void classGetClassesShouldMatchDeclaredClasses() {
hints.reflection().registerType(String.class, MemberCategory.DECLARED_CLASSES);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCLASSES, this.stringGetClasses);
}
@Test
void classGetDeclaredClassesShouldMatchDeclaredClassesHint() {
hints.reflection().registerType(String.class, MemberCategory.DECLARED_CLASSES);
void classGetDeclaredClassesShouldMatchReflectionOnType() {
hints.reflection().registerType(String.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCLASSES, this.stringGetDeclaredClasses);
}
@Test
void classGetDeclaredClassesShouldNotMatchPublicClassesHint() {
hints.reflection().registerType(String.class, MemberCategory.PUBLIC_CLASSES);
void classGetDeclaredClassesShouldNotMatchWhenMissingReflectionOnType() {
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDCLASSES, this.stringGetDeclaredClasses);
}
@ -124,36 +118,28 @@ class InstrumentedMethodTests {
}
@Test
void classGetConstructorShouldMatchIntrospectPublicConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS);
void classGetConstructorShouldMatchTypeHint() {
hints.reflection().registerType(String.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
}
@Test
void classGetConstructorShouldNotMatchWhenMissingTypeHint() {
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
}
@Test
void classGetConstructorShouldMatchInvokePublicConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
}
@Test
void classGetConstructorShouldMatchIntrospectDeclaredConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
}
@Test
void classGetConstructorShouldMatchInvokeDeclaredConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
}
@Test
void classGetConstructorShouldMatchIntrospectConstructorHint() {
hints.reflection().registerType(String.class,typeHint ->
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
}
@Test
void classGetConstructorShouldMatchInvokeConstructorHint() {
hints.reflection().registerType(String.class, typeHint ->
@ -162,23 +148,22 @@ class InstrumentedMethodTests {
}
@Test
void classGetConstructorsShouldMatchIntrospectPublicConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS);
void classGetConstructorsShouldMatchTypeHint() {
hints.reflection().registerType(String.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
}
@Test
void classGetConstructorsShouldNotMatchWhemMissingTypeHint() {
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
}
@Test
void classGetConstructorsShouldMatchInvokePublicConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
}
@Test
void classGetConstructorsShouldMatchIntrospectDeclaredConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
}
@Test
void classGetConstructorsShouldMatchInvokeDeclaredConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
@ -186,36 +171,16 @@ class InstrumentedMethodTests {
}
@Test
void classGetConstructorsShouldNotMatchTypeReflectionHint() {
void classGetDeclaredConstructorShouldMatchTypeHint() {
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
}
@Test
void classGetConstructorsShouldNotMatchConstructorReflectionHint() throws Exception {
hints.reflection().registerConstructor(String.class.getConstructor(), ExecutableMode.INVOKE);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
}
@Test
void classGetDeclaredConstructorShouldMatchIntrospectDeclaredConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
}
@Test
void classGetDeclaredConstructorShouldNotMatchIntrospectPublicConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS);
void classGetDeclaredConstructorShouldNotMatchWhenMissingTypeHint() {
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
}
@Test
void classGetDeclaredConstructorShouldMatchIntrospectConstructorHint() {
hints.reflection().registerType(String.class, typeHint ->
typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), ExecutableMode.INTROSPECT));
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
}
@Test
void classGetDeclaredConstructorShouldMatchInvokeConstructorHint() {
hints.reflection().registerType(String.class, typeHint ->
@ -223,12 +188,6 @@ class InstrumentedMethodTests {
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
}
@Test
void classGetDeclaredConstructorsShouldMatchIntrospectDeclaredConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_CONSTRUCTORS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTORS, this.stringGetDeclaredConstructors);
}
@Test
void classGetDeclaredConstructorsShouldMatchInvokeDeclaredConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
@ -236,20 +195,13 @@ class InstrumentedMethodTests {
}
@Test
void classGetDeclaredConstructorsShouldNotMatchIntrospectPublicConstructorsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_CONSTRUCTORS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTORS, this.stringGetDeclaredConstructors);
}
@Test
void classGetDeclaredConstructorsShouldNotMatchTypeReflectionHint() {
void classGetDeclaredConstructorsShouldMatchTypeReflectionHint() {
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTORS, this.stringGetDeclaredConstructors);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTORS, this.stringGetDeclaredConstructors);
}
@Test
void classGetDeclaredConstructorsShouldNotMatchConstructorReflectionHint() throws Exception {
hints.reflection().registerConstructor(String.class.getConstructor(), ExecutableMode.INVOKE);
void classGetDeclaredConstructorsShouldNotMatchWhenMissingTypeReflectionHint() {
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTORS, this.stringGetDeclaredConstructors);
}
@ -262,15 +214,6 @@ class InstrumentedMethodTests {
assertThatInvocationMatches(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation);
}
@Test
void constructorNewInstanceShouldNotMatchIntrospectHintOnConstructor() throws NoSuchMethodException {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE)
.onInstance(String.class.getConstructor()).returnValue("").build();
hints.reflection().registerType(String.class, typeHint ->
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
assertThatInvocationDoesNotMatch(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation);
}
}
@Nested
@ -295,22 +238,8 @@ class InstrumentedMethodTests {
}
@Test
void classGetDeclaredMethodShouldMatchIntrospectDeclaredMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_METHODS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
}
@Test
void classGetDeclaredMethodShouldNotMatchIntrospectPublicMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
}
@Test
void classGetDeclaredMethodShouldMatchIntrospectMethodHint() {
List<TypeReference> parameterTypes = TypeReference.listOf(int.class, float.class);
hints.reflection().registerType(String.class, typeHint ->
typeHint.withMethod("scale", parameterTypes, ExecutableMode.INTROSPECT));
void classGetDeclaredMethodShouldMatchTypeReflectionHint() {
hints.reflection().registerType(String.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
}
@ -322,12 +251,6 @@ class InstrumentedMethodTests {
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
}
@Test
void classGetDeclaredMethodsShouldMatchIntrospectDeclaredMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_METHODS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHODS, this.stringGetScaleMethod);
}
@Test
void classGetDeclaredMethodsShouldMatchInvokeDeclaredMethodsHint() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETDECLAREDMETHODS).onInstance(String.class).build();
@ -336,32 +259,8 @@ class InstrumentedMethodTests {
}
@Test
void classGetDeclaredMethodsShouldNotMatchIntrospectPublicMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDMETHODS, this.stringGetScaleMethod);
}
@Test
void classGetDeclaredMethodsShouldNotMatchTypeReflectionHint() {
void classGetMethodsShouldMatchTypeReflectionHint() {
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDMETHODS, this.stringGetScaleMethod);
}
@Test
void classGetDeclaredMethodsShouldNotMatchMethodReflectionHint() throws Exception {
hints.reflection().registerMethod(String.class.getMethod("toString"), ExecutableMode.INVOKE);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDMETHODS, this.stringGetScaleMethod);
}
@Test
void classGetMethodsShouldMatchIntrospectDeclaredMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_METHODS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHODS, this.stringGetMethods);
}
@Test
void classGetMethodsShouldMatchIntrospectPublicMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHODS, this.stringGetMethods);
}
@ -379,25 +278,13 @@ class InstrumentedMethodTests {
@Test
void classGetMethodsShouldNotMatchForWrongType() {
hints.reflection().registerType(Integer.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
hints.reflection().registerType(Integer.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHODS, this.stringGetMethods);
}
@Test
void classGetMethodsShouldNotMatchTypeReflectionHint() {
void classGetMethodShouldMatchReflectionTypeHint() {
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHODS, this.stringGetMethods);
}
@Test
void classGetMethodsShouldNotMatchMethodReflectionHint() throws Exception {
hints.reflection().registerMethod(String.class.getMethod("toString"), ExecutableMode.INVOKE);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHODS, this.stringGetMethods);
}
@Test
void classGetMethodShouldMatchIntrospectPublicMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
}
@ -407,25 +294,6 @@ class InstrumentedMethodTests {
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
}
@Test
void classGetMethodShouldNotMatchIntrospectDeclaredMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_METHODS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
}
@Test
void classGetMethodShouldNotMatchInvokeDeclaredMethodsHint() {
hints.reflection().registerType(String.class, MemberCategory.INVOKE_DECLARED_METHODS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
}
@Test
void classGetMethodShouldMatchIntrospectMethodHint() {
hints.reflection().registerType(String.class, typeHint ->
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT));
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
}
@Test
void classGetMethodShouldMatchInvokeMethodHint() {
hints.reflection().registerType(String.class, typeHint ->
@ -433,21 +301,9 @@ class InstrumentedMethodTests {
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
}
@Test
void classGetMethodShouldNotMatchIntrospectPublicMethodsHintWhenPrivate() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetScaleMethod);
}
@Test
void classGetMethodShouldMatchIntrospectDeclaredMethodsHintWhenPrivate() {
hints.reflection().registerType(String.class, MemberCategory.INTROSPECT_DECLARED_METHODS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetScaleMethod);
}
@Test
void classGetMethodShouldNotMatchForWrongType() {
hints.reflection().registerType(Integer.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
hints.reflection().registerType(Integer.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
}
@ -461,11 +317,10 @@ class InstrumentedMethodTests {
}
@Test
void methodInvokeShouldNotMatchIntrospectHintOnMethod() throws NoSuchMethodException {
void methodInvokeShouldNotMatchReflectionTypeHint() throws NoSuchMethodException {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.METHOD_INVOKE)
.onInstance(String.class.getMethod("toString")).withArguments("", new Object[0]).build();
hints.reflection().registerType(String.class, typeHint ->
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT));
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.METHOD_INVOKE, invocation);
}
@ -496,17 +351,11 @@ class InstrumentedMethodTests {
}
@Test
void classGetDeclaredFieldShouldMatchDeclaredFieldsHint() {
hints.reflection().registerType(String.class, MemberCategory.DECLARED_FIELDS);
void classGetDeclaredFieldShouldMatchTypeReflectionHint() {
hints.reflection().registerType(String.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDFIELD, this.stringGetDeclaredField);
}
@Test
void classGetDeclaredFieldShouldNotMatchPublicFieldsHint() {
hints.reflection().registerType(String.class, typeHint -> typeHint.withMembers(MemberCategory.PUBLIC_FIELDS));
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDFIELD, this.stringGetDeclaredField);
}
@Test
void classGetDeclaredFieldShouldMatchFieldHint() {
hints.reflection().registerType(String.class, typeHint -> typeHint.withField("value"));
@ -514,41 +363,23 @@ class InstrumentedMethodTests {
}
@Test
void classGetDeclaredFieldsShouldMatchDeclaredFieldsHint() {
hints.reflection().registerType(String.class, MemberCategory.DECLARED_FIELDS);
void classGetDeclaredFieldsShouldMatchTypeReflectionHint() {
hints.reflection().registerType(String.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDFIELDS, this.stringGetDeclaredFields);
}
@Test
void classGetDeclaredFieldsShouldNotMatchPublicFieldsHint() {
hints.reflection().registerType(String.class, MemberCategory.PUBLIC_FIELDS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDFIELDS, this.stringGetDeclaredFields);
}
@Test
void classGetDeclaredFieldsShouldNotMatchTypeHint() {
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDFIELDS, this.stringGetDeclaredFields);
}
@Test
void classGetDeclaredFieldsShouldNotMatchFieldHint() throws Exception {
void classGetDeclaredFieldsShouldMatchFieldHint() throws Exception {
hints.reflection().registerField(String.class.getDeclaredField("value"));
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETDECLAREDFIELDS, this.stringGetDeclaredFields);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDFIELDS, this.stringGetDeclaredFields);
}
@Test
void classGetFieldShouldMatchPublicFieldsHint() {
hints.reflection().registerType(PublicField.class, MemberCategory.PUBLIC_FIELDS);
void classGetFieldShouldMatchTypeReflectionHint() {
hints.reflection().registerType(PublicField.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETFIELD, this.getPublicField);
}
@Test
void classGetFieldShouldNotMatchDeclaredFieldsHint() {
hints.reflection().registerType(PublicField.class, MemberCategory.DECLARED_FIELDS);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETFIELD, this.getPublicField);
}
@Test
void classGetFieldShouldMatchFieldHint() {
hints.reflection().registerType(PublicField.class, typeHint -> typeHint.withField("field"));
@ -559,53 +390,30 @@ class InstrumentedMethodTests {
void classGetFieldShouldNotMatchPublicFieldsHintWhenPrivate() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETFIELD)
.onInstance(String.class).withArgument("value").returnValue(null).build();
hints.reflection().registerType(String.class, MemberCategory.PUBLIC_FIELDS);
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETFIELD, invocation);
}
@Test
void classGetFieldShouldMatchDeclaredFieldsHintWhenPrivate() throws NoSuchFieldException {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETFIELD)
.onInstance(String.class).withArgument("value").returnValue(String.class.getDeclaredField("value")).build();
hints.reflection().registerType(String.class, MemberCategory.DECLARED_FIELDS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETFIELD, invocation);
}
@Test
void classGetFieldShouldNotMatchForWrongType() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETFIELD)
.onInstance(String.class).withArgument("value").returnValue(null).build();
hints.reflection().registerType(Integer.class, MemberCategory.DECLARED_FIELDS);
hints.reflection().registerType(Integer.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETFIELD, invocation);
}
@Test
void classGetFieldsShouldMatchPublicFieldsHint() {
void classGetFieldsShouldMatchReflectionHint() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETFIELDS)
.onInstance(PublicField.class).build();
hints.reflection().registerType(PublicField.class, MemberCategory.PUBLIC_FIELDS);
hints.reflection().registerType(PublicField.class);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETFIELDS, invocation);
}
@Test
void classGetFieldsShouldMatchDeclaredFieldsHint() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETFIELDS)
.onInstance(PublicField.class).build();
hints.reflection().registerType(PublicField.class, MemberCategory.DECLARED_FIELDS);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETFIELDS, invocation);
}
@Test
void classGetFieldsShouldNotMatchTypeHint() {
void classGetFieldsShouldMatchTypeHint() {
hints.reflection().registerType(String.class);
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETFIELDS, this.stringGetFields);
}
@Test
void classGetFieldsShouldNotMatchFieldHint() throws Exception {
hints.reflection().registerField(String.class.getDeclaredField("value"));
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETFIELDS, this.stringGetFields);
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETFIELDS, this.stringGetFields);
}
}
@ -634,7 +442,7 @@ class InstrumentedMethodTests {
void classGetResourceShouldMatchResourcePatternWhenAbsolute() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETRESOURCE)
.onInstance(InstrumentedMethodTests.class).withArgument("/some/path/resource.txt").build();
hints.resources().registerPattern("some/*");
hints.resources().registerPattern("some/**");
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETRESOURCE, invocation);
}
@ -655,11 +463,11 @@ class InstrumentedMethodTests {
}
@Test
void classGetResourceShouldNotMatchResourcePatternWhenExcluded() {
void classGetResourceShouldMatchWhenGlobPattern() {
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CLASS_GETRESOURCE)
.onInstance(InstrumentedMethodTests.class).withArgument("/some/path/resource.txt").build();
hints.resources().registerPattern(resourceHint -> resourceHint.includes("some/*").excludes("some/path/*"));
assertThatInvocationDoesNotMatch(InstrumentedMethod.CLASS_GETRESOURCE, invocation);
hints.resources().registerPattern(resourceHint -> resourceHint.includes("some/**"));
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETRESOURCE, invocation);
}
}