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

ru.saidgadjiev.proxymaker.bytecode.ByteCodeUtils Maven / Gradle / Ivy

The newest version!
package ru.saidgadjiev.proxymaker.bytecode;

import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Utils for bytecode instructions.
 */
public final class ByteCodeUtils {

    /**
     * Utils class instance cant't be created.
     */
    private ByteCodeUtils() { }

    /**
     * Convert {@link List} to byte array.
     *
     * @param list target list
     * @return byte array
     */
    public static byte[] toByteArray(List list) {
        byte[] array = new byte[list.size()];
        AtomicInteger index = new AtomicInteger();

        list.forEach(aByte -> array[index.getAndIncrement()] = aByte);

        return array;
    }

    /**
     * Convert classname to jvm represent.
     *
     * @param classname target fully-qualified classname
     * @return jvm classname where . replaced by /
     */
    public static String toJvmName(String classname) {
        return classname.replace('.', '/');
    }

    /**
     * Size of descriptor for bytecode.
     *
     * @param desc target descriptor
     * @return size of desc
     */
    public static int dataSize(String desc) {
        int n = 0;
        char c = desc.charAt(0);
        if (c == '(') {
            int i = 1;

            while (true) {
                c = desc.charAt(i);
                if (c == ')') {
                    c = desc.charAt(i + 1);
                    break;
                }

                boolean array = false;
                while (c == '[') {
                    array = true;
                    c = desc.charAt(++i);
                }

                if (c == 'L') {
                    i = desc.indexOf(';', i) + 1;
                    if (i <= 0) {
                        throw new IndexOutOfBoundsException("bad descriptor");
                    }
                } else {
                    ++i;
                }
                if (!array && (c == 'J' || c == 'D')) {
                    n -= 2;
                } else {
                    --n;
                }
            }
        }
        if (c == 'J' || c == 'D') {
            n += 2;
        } else if (c != 'V') {
            ++n;
        }

        return n;
    }

    /**
     * Make {@link Method} decriptor for bytecode.
     *
     * @param method target method
     * @return method descriptor
     */
    public static String makeDescriptor(Method method) {
        Class[] params = method.getParameterTypes();

        return makeDescriptor(params, method.getReturnType());
    }

    /**
     * Make decriptor for bytecode by {@code params} and {@code retType}.
     *
     * @param params target params
     * @param retType target return type
     * @return method descriptor
     */
    public static String makeDescriptor(Class[] params, Class retType) {
        StringBuilder sbuf = new StringBuilder();

        sbuf.append('(');
        for (Class param : params) {
            makeDesc(sbuf, param);
        }

        sbuf.append(')');
        if (retType != null) {
            makeDesc(sbuf, retType);
        }

        return sbuf.toString();
    }

    /**
     * Make decriptor for bytecode by {@code type}.
     *
     * @param sbuf buffer for write descriptor chars
     * @param type target type
     * @return type descriptor
     */
    private static String makeDesc(StringBuilder sbuf, Class type) {
        if (type.isArray()) {
            sbuf.append('[');
            makeDesc(sbuf, type.getComponentType());
        } else if (type.isPrimitive()) {
            if (type == Void.TYPE) {
                sbuf.append('V');
            } else if (type == Integer.TYPE) {
                sbuf.append('I');
            } else if (type == Byte.TYPE) {
                sbuf.append('B');
            } else if (type == Long.TYPE) {
                sbuf.append('J');
            } else if (type == Double.TYPE) {
                sbuf.append('D');
            } else if (type == Float.TYPE) {
                sbuf.append('F');
            } else if (type == Character.TYPE) {
                sbuf.append('C');
            } else if (type == Short.TYPE) {
                sbuf.append('S');
            } else if (type == Boolean.TYPE) {
                sbuf.append('Z');
            } else {
                throw new RuntimeException("bad type: " + type.getName());
            }
        } else {
            sbuf.append('L').append(type.getName().replace('.', '/'))
                    .append(';');
        }

        return sbuf.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy