use of com.newrelic.weave.utils.SynchronizedMethodNode in project newrelic-java-agent by newrelic.
the class Reference method addMethodsAndFields.
/**
* Fetch all methods and fields of a class node including those inherited from supertypes+interfaces. The results
* will be stored in the passed in methods and fields lists.
*
* @param classCache Cache to use to fetch supertype resources
* @param classNode The node to scan
* @param methods classNode's methods will be appended to this list.
* @param fields classNode's fields will be appended to this list.
*/
private static void addMethodsAndFields(ClassCache classCache, ClassNode classNode, List<MethodNode> methods, List<FieldNode> fields) throws IOException {
ClassInformation classInfo = classCache.getClassInformation(classNode.name);
for (MemberInformation methodInfo : classInfo.getAllMethods(classCache)) {
MethodNode methodNode = new SynchronizedMethodNode();
methodNode.name = methodInfo.name;
methodNode.desc = methodInfo.desc;
methodNode.access = methodInfo.access;
methods.add(methodNode);
}
for (MemberInformation fieldInfo : classInfo.getAllFields(classCache)) {
fields.add(new SynchronizedFieldNode(WeaveUtils.ASM_API_LEVEL, fieldInfo.access, fieldInfo.name, fieldInfo.desc, null, null));
}
}
use of com.newrelic.weave.utils.SynchronizedMethodNode in project newrelic-java-agent by newrelic.
the class ErrorTrapWeaveMethodsProcessor method process.
/**
* This method processor will wrap weave code with try/catch blocks. Weaver.callOriginal() will not be wrapped.
* <p/>
*
* When weave code throws an unexpected exception (an exception thrown without an explicit throw call), the error
* handler will be invoked and then the original return value will be returned. The error handler may throw an
* exception to prevent the original return value from being returned.
* <p/>
*
* Weave code which occurs before callOriginal is the preamble. Weave code which occurs after callOriginal is the
* postamble.
*
* @return
*/
public MethodNode process() {
if (errorTrapHandler == ErrorTrapHandler.NO_ERROR_TRAP_HANDLER) {
return this.trappedMethod;
}
Type originalReturnType = Type.getReturnType(trappedMethod.desc);
boolean isVoid = originalReturnType.equals(Type.VOID_TYPE);
if ((null == startOfOriginalMethodLabelNode || null == endOfOriginalMethodLabelNode) && !isVoid) {
// no support for error-trapping non-void methods which do not call Weaver.callOriginal()
return trappedMethod;
}
List<TryCatchBlockNode> priorityTryCatch = new ArrayList<>();
if (null != trappedMethod.tryCatchBlocks) {
// weave try/catch blocks take priority over error-trap
priorityTryCatch.addAll(trappedMethod.tryCatchBlocks);
}
// Used to write the bytecode for error trapping
MethodNode generatorMethod = new SynchronizedMethodNode(WeaveUtils.ASM_API_LEVEL);
GeneratorAdapter generator = new GeneratorAdapter(trappedMethod.access, new Method(trappedMethod.name, trappedMethod.desc), generatorMethod);
// Any errors which are explicitly thrown will not go through the error trap.
LocalVariableNode weaveExplicitThrow = null;
if (isThrowCalled(trappedMethod)) {
// create a variable to store the explicit throw
weaveExplicitThrow = new LocalVariableNode("weaveExplicitThrow", Type.getDescriptor(Throwable.class), null, startOfTrapLabelNode, endOfTrapLabelNode, findIndexForNewLocal(trappedMethod));
trappedMethod.maxLocals++;
generator.push((String) null);
generator.storeLocal(weaveExplicitThrow.index, Type.getType(Throwable.class));
trappedMethod.visitLocalVariable(weaveExplicitThrow.name, weaveExplicitThrow.desc, weaveExplicitThrow.signature, weaveExplicitThrow.start.getLabel(), weaveExplicitThrow.end.getLabel(), weaveExplicitThrow.index);
ErrorTrapWeaveMethodsProcessor.storeExceptionAtThrowSites(trappedMethod, weaveExplicitThrow.index);
trappedMethod.instructions.insertBefore(startOfTrapLabelNode, generatorMethod.instructions);
}
if (null == startOfOriginalMethodLabelNode || null == endOfOriginalMethodLabelNode) {
// a void method which does not call Weaver.callOriginal. Probably a constructor.
// @formatter:off
/*-
* Throwable weaveExplicitThrow = null;
* try{
* //weave code
* }
* catch(Throwable t){
* if(null != weaveExplicitThrow)
* throw t;
* errorHandle(t);
* return;
* }
*/
// @formatter:on
generator.goTo(endOfTrapLabelNode.getLabel());
Label handler = new Label();
generator.visitLabel(handler);
if (null != weaveExplicitThrow) {
writeRethrowExplicitThrow(generator, weaveExplicitThrow);
}
this.writeHandler(generator, errorTrapHandler);
trappedMethod.instructions.insertBefore(endOfTrapLabelNode, generatorMethod.instructions);
trappedMethod.visitTryCatchBlock(startOfTrapLabelNode.getLabel(), handler, handler, Type.getInternalName(Throwable.class));
} else {
// @formatter:off
/*-
* Throwable weaveExplicitThrow = null;
* boolean weaveThrowableWasThrown = false;
* try{
* //weave preamble
* }
* catch(Throwable t){
* if(null != weaveExplicitThrow)
* throw t;
* errorHandle(t)
* weaveExceptionWasThrown = true;
* }
* Object weaveOriginalReturnVale = Weaver.callOriginal()
* if(weaveExceptionWasThrown){
* return weaveOriginalReturnValue
* }
* try{
* //weave postamble
* }
* catch(Throwable t){
* if(null != weaveExplicitThrow)
* throw t;
* errorHandle(t)
* return weaveOriginalReturnValue
* }
*/
// @formatter:on
LocalVariableNode weaveThrowableWasThrown;
LocalVariableNode weaveOriginalReturnValue = null;
LabelNode localsStart = WeaveUtils.makeLabelNode();
trappedMethod.instructions.insert(localsStart);
initializePreambleLocals(trappedMethod, startOfOriginalMethodLabelNode, localsStart);
// Store the original return value in a new local variable
if (!isVoid) {
weaveOriginalReturnValue = new LocalVariableNode("weaveOriginalReturnValue", originalReturnType.getDescriptor(), null, startOfTrapLabelNode, endOfTrapLabelNode, findIndexForNewLocal(trappedMethod));
trappedMethod.maxLocals++;
trappedMethod.visitLocalVariable(weaveOriginalReturnValue.name, weaveOriginalReturnValue.desc, weaveOriginalReturnValue.signature, weaveOriginalReturnValue.start.getLabel(), weaveOriginalReturnValue.end.getLabel(), weaveOriginalReturnValue.index);
storeOriginalReturnValue(generatorMethod, generator, trappedMethod, startOfOriginalMethodLabelNode, endOfOriginalMethodLabelNode, weaveOriginalReturnValue);
}
// add and initialize weaveThrowableWasThrown
{
// generator.visitLabel(localsStart.getLabel());
weaveThrowableWasThrown = new LocalVariableNode("weaveThrowableWasThrown", Type.BOOLEAN_TYPE.getDescriptor(), null, startOfTrapLabelNode, endOfTrapLabelNode, findIndexForNewLocal(trappedMethod));
trappedMethod.maxLocals++;
trappedMethod.visitLocalVariable(weaveThrowableWasThrown.name, weaveThrowableWasThrown.desc, weaveThrowableWasThrown.signature, weaveThrowableWasThrown.start.getLabel(), weaveThrowableWasThrown.end.getLabel(), weaveThrowableWasThrown.index);
writeStoreInitialValue(generator, weaveThrowableWasThrown);
if (!isVoid) {
writeStoreInitialValue(generator, weaveOriginalReturnValue);
}
trappedMethod.instructions.insertBefore(startOfTrapLabelNode, generatorMethod.instructions);
}
// handler for preabmle
{
generator.goTo(startOfOriginalMethodLabelNode.getLabel());
Label preambleHandler = new Label();
generator.visitLabel(preambleHandler);
if (null != weaveExplicitThrow) {
writeRethrowExplicitThrow(generator, weaveExplicitThrow);
}
writeHandler(generator, errorTrapHandler);
generator.push(true);
generator.storeLocal(weaveThrowableWasThrown.index, Type.BOOLEAN_TYPE);
trappedMethod.instructions.insertBefore(startOfOriginalMethodLabelNode, generatorMethod.instructions);
trappedMethod.visitTryCatchBlock(startOfTrapLabelNode.getLabel(), preambleHandler, preambleHandler, Type.getInternalName(Throwable.class));
}
// return weaveOriginalReturnValue if weaveThrowableWasThrown
{
LabelNode continueMethod = WeaveUtils.makeLabelNode();
generator.push(false);
generator.loadLocal(weaveThrowableWasThrown.index);
generator.ifICmp(Opcodes.IFEQ, continueMethod.getLabel());
if (isVoid) {
generator.visitInsn(Opcodes.RETURN);
} else {
generator.loadLocal(weaveOriginalReturnValue.index);
generator.returnValue();
}
generator.visitLabel(continueMethod.getLabel());
trappedMethod.instructions.insertBefore(endOfOriginalMethodLabelNode, generatorMethod.instructions);
}
// handler for postamble
{
Label postambleHandler = new Label();
generator.visitLabel(postambleHandler);
if (null != weaveExplicitThrow) {
writeRethrowExplicitThrow(generator, weaveExplicitThrow);
}
writeHandler(generator, errorTrapHandler);
if (isVoid) {
generator.visitInsn(Opcodes.RETURN);
} else {
generator.loadLocal(weaveOriginalReturnValue.index);
generator.returnValue();
}
trappedMethod.instructions.insertBefore(endOfTrapLabelNode, generatorMethod.instructions);
trappedMethod.visitTryCatchBlock(endOfOriginalMethodLabelNode.getLabel(), postambleHandler, postambleHandler, Type.getInternalName(Throwable.class));
}
}
if (trappedMethod.tryCatchBlocks != null && priorityTryCatch.size() > 0) {
sortTryCatchBlocks(trappedMethod, priorityTryCatch);
}
trappedMethod.instructions.resetLabels();
return trappedMethod;
}
Aggregations