cn.taketoday.aot.agent.RecordedInvocation Maven / Gradle / Ivy
/*
* Copyright 2017 - 2023 the original author or authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see [http://www.gnu.org/licenses/]
*/
package cn.taketoday.aot.agent;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
import cn.taketoday.aot.hint.RuntimeHints;
import cn.taketoday.aot.hint.TypeReference;
import cn.taketoday.lang.Assert;
import cn.taketoday.lang.Nullable;
/**
* Record of an invocation of a method relevant to {@link cn.taketoday.aot.hint.RuntimeHints}.
* The {@link RuntimeHintsAgent} instruments bytecode and intercepts invocations of
* {@link InstrumentedMethod specific methods}; invocations are recorded during test execution
* to match them against an existing {@link cn.taketoday.aot.hint.RuntimeHints} configuration.
*
* @author Brian Clozel
* @since 4.0
*/
public final class RecordedInvocation {
@Nullable
private final Object instance;
private final InstrumentedMethod instrumentedMethod;
private final Object[] arguments;
@Nullable
private final Object returnValue;
private final List stackFrames;
private RecordedInvocation(InstrumentedMethod instrumentedMethod, @Nullable Object instance,
Object[] arguments, @Nullable Object returnValue, List stackFrames) {
this.instance = instance;
this.instrumentedMethod = instrumentedMethod;
this.arguments = arguments;
this.returnValue = returnValue;
this.stackFrames = stackFrames;
}
/**
* Initialize a builder for the given {@link InstrumentedMethod}.
*
* @param instrumentedMethod the instrumented method
* @return a builder
*/
public static Builder of(InstrumentedMethod instrumentedMethod) {
Assert.notNull(instrumentedMethod, "InstrumentedMethod is required");
return new Builder(instrumentedMethod);
}
/**
* Return the category of {@link RuntimeHints} this invocation relates to.
*
* @return the hint type
*/
public HintType getHintType() {
return this.instrumentedMethod.getHintType();
}
/**
* Return a simple representation of the method invoked here.
*
* @return the method reference
*/
public MethodReference getMethodReference() {
return this.instrumentedMethod.methodReference();
}
/**
* Return the stack trace of the current invocation.
*
* @return the stack frames
*/
public Stream getStackFrames() {
return this.stackFrames.stream();
}
/**
* Return the instance of the object being invoked.
*
* @return the object instance
* @throws IllegalStateException in case of static invocations (there is no {@code this})
*/
@SuppressWarnings("unchecked")
public T getInstance() {
Assert.state(this.instance != null, "Cannot resolve 'this' for static invocations");
return (T) this.instance;
}
/**
* Return the Type reference of the object being invoked.
*
* @return the instance type reference, or {@code null}
* @throws IllegalStateException in case of static invocations (there is no {@code this})
*/
public TypeReference getInstanceTypeReference() {
Assert.state(this.instance != null, "Cannot resolve 'this' for static invocations");
return TypeReference.of(this.instance.getClass());
}
/**
* Return whether the current invocation is static.
*
* @return {@code true} if the invocation is static
*/
public boolean isStatic() {
return this.instance == null;
}
/**
* Return the argument values used for the current reflection invocation.
*
* @return the invocation arguments
*/
public List