All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.quartercode.jtimber.rh.agent.util.ASMUtils Maven / Gradle / Ivy

Go to download

The runtime bytecode manipulator in form of a java agent that implements some framework features by injecting code into tree classes.

The newest version!
/*
 * This file is part of JTimber.
 * Copyright (c) 2015 QuarterCode 
 *
 * JTimber 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.
 *
 * JTimber 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 JTimber. If not, see .
 */

package com.quartercode.jtimber.rh.agent.util;

import static org.objectweb.asm.Opcodes.*;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;

/**
 * A utility class which contains some utility methods used by ASM transformers.
 */
public class ASMUtils {

    private static final String API_PCKG           = "com/quartercode/jtimber/api";
    private static final String PARENT_AWARE_CLASS = API_PCKG + "/node/ParentAware";
    private static final String NODE_DESC          = "L" + API_PCKG + "/node/Node;";

    /**
     * Generates the instructions to push a non-static field onto the stack and box it in case it is a primitive.
     * This is just a handy shortcut. However, it requires a {@link GeneratorAdapter} method visitor.
     * 
     * @param mg The method visitor that should be used to generate the instructions (must be a generator adapter).
     * @param classType The {@link Type} of the class which contains the field.
     * @param fieldName The name of the field.
     * @param fieldType The type of the field.
     */
    public static void generateGetField(GeneratorAdapter mg, Type classType, String fieldName, Type fieldType) {

        // Push the object stored in the field
        mg.loadThis();
        mg.getField(classType, fieldName, fieldType);

        // Box the object in case it is a primitive
        mg.box(fieldType);
    }

    /**
     * Generates the instructions to call the {@code addParent()} or {@code removeParent()} method on an object using {@code this} as the parent.
     * Note that an instanceof check is be executed beforehand in order to check whether the object is non-null and parent-aware.
*
* The object the operation should be performed on needs to be the topmost value on the stack when the generated instructions are entered. * The rest of the stack is ignored by the generated instructions. * * @param mv The {@link MethodVisitor} that should be used to generate the instructions. * @param methodName The name of the method to call ({@code "addParent"} or {@code "removeParent"}). */ public static void generateAddOrRemoveThisAsParent(MethodVisitor mv, String methodName) { // Skip the if-block if the condition below isn't true Label endIf = new Label(); mv.visitInsn(DUP); mv.visitTypeInsn(INSTANCEOF, PARENT_AWARE_CLASS); mv.visitJumpInsn(IFEQ, endIf); /* if (object instanceof ParentAware) */ { // Push a copy of the value because the parent watcher method will be invoked on it mv.visitInsn(DUP); // Push "this" because it will be used as the first argument for the following method call mv.visitVarInsn(ALOAD, 0); // Invoke the parent watcher method on the value (which implements the "ParentAware" interface) using "this" as the first argument mv.visitMethodInsn(INVOKEINTERFACE, PARENT_AWARE_CLASS, methodName, "(" + NODE_DESC + ")V", true); } mv.visitLabel(endIf); } private ASMUtils() { } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy