/* * Copyright 2008-2009 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.hasor.core.classcode; import net.hasor.core.classcode.asm.Opcodes; import net.hasor.core.classcode.asm.Type; import java.io.IOException; import java.io.StringReader; import java.lang.reflect.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * 生成字节码时候使用的工具类。 * @version 2009-10-16 * @author 赵永春 (zyc@hasor.net) */ public class ASMEngineTools implements Opcodes { /** <p>The package separator character: <code>'.' == {@value}</code>.</p> */ public static final char PACKAGE_SEPARATOR_CHAR = '.'; /** <p>The inner class separator character: <code>'$' == {@value}</code>.</p> */ public static final char INNER_CLASS_SEPARATOR_CHAR = '$'; /** Maps a primitive class name to its corresponding abbreviation used in array class names. */ private static final Map<String, String> abbreviationMap = new HashMap<String, String>(); /** Maps an abbreviation used in array class names to corresponding primitive class name. */ private static final Map<String, String> reverseAbbreviationMap = new HashMap<String, String>(); /** * Add primitive type abbreviation to maps of abbreviations. * @param primitive Canonical name of primitive type * @param abbreviation Corresponding abbreviation of primitive type */ private static void addAbbreviation(final String primitive, final String abbreviation) { abbreviationMap.put(primitive, abbreviation); reverseAbbreviationMap.put(abbreviation, primitive); } /** Feed abbreviation maps */ static { addAbbreviation("int", "I"); addAbbreviation("boolean", "Z"); addAbbreviation("float", "F"); addAbbreviation("long", "J"); addAbbreviation("short", "S"); addAbbreviation("byte", "B"); addAbbreviation("double", "D"); addAbbreviation("char", "C"); } //======================================================================================================================= /**根据类型获取其Return指令。*/ public static int getReturn(final String asmType) { char t = asmType.charAt(0); switch (t) { case 'B': return Opcodes.IRETURN;//Byte case 'C': return Opcodes.IRETURN;//Char case 'D': return Opcodes.DRETURN;//Double case 'F': return Opcodes.FRETURN;//Float case 'I': return Opcodes.IRETURN;//Integer case 'J': return Opcodes.LRETURN;//Long case 'L': return Opcodes.ARETURN;//Ref case 'S': return Opcodes.IRETURN;//Short case 'Z': return Opcodes.IRETURN;//Boolean case '[': return Opcodes.ARETURN;//Array case 'V': return Opcodes.RETURN;//Void default: throw new UnsupportedOperationException("不支持的类型装载请求");// } } /**根据类型获取其Load指令。*/ public static int getLoad(final String asmType) { char t = asmType.charAt(0); switch (t) { case 'B': return Opcodes.ILOAD;//Byte case 'C': return Opcodes.ILOAD;//Char case 'D': return Opcodes.DLOAD;//Double case 'F': return Opcodes.FLOAD;//Float case 'I': return Opcodes.ILOAD;//Integer case 'J': return Opcodes.LLOAD;//Long case 'L': return Opcodes.ALOAD;//Ref case 'S': return Opcodes.ILOAD;//Short case 'Z': return Opcodes.ILOAD;//Boolean case '[': return Opcodes.ALOAD;//Array default: throw new UnsupportedOperationException("不支持的类型装载请求");// } } /**根据asm类型获取其ASTORE指令。*/ public static int getAstore(final String asmType) { char t = asmType.charAt(0); switch (t) { case 'B': return Opcodes.IASTORE;//Byte case 'C': return Opcodes.IASTORE;//Char case 'D': return Opcodes.DASTORE;//Double case 'F': return Opcodes.FASTORE;//Float case 'I': return Opcodes.IASTORE;//Integer case 'J': return Opcodes.LASTORE;//Long case 'L': return Opcodes.AASTORE;//Ref case 'S': return Opcodes.IASTORE;//Short case 'Z': return Opcodes.IASTORE;//Boolean case '[': return Opcodes.AASTORE;//Array default: throw new UnsupportedOperationException("不支持的类型装载请求");// } } //======================================================================================================================= /**将某一个类型转为asm形式的表述, int 转为 I,String转为 Ljava/lang/String。*/ public static String toAsmType(final Class<?> classType) { if (classType == int.class) { return "I"; } else if (classType == byte.class) { return "B"; } else if (classType == char.class) { return "C"; } else if (classType == double.class) { return "D"; } else if (classType == float.class) { return "F"; } else if (classType == long.class) { return "J"; } else if (classType == short.class) { return "S"; } else if (classType == boolean.class) { return "Z"; } else if (classType == void.class) { return "V"; } else if (classType.isArray()) { return "[" + ASMEngineTools.toAsmType(classType.getComponentType()); } else { return "L" + Type.getInternalName(classType) + ";"; } } /**将某一个类型转为asm形式的表述, int,int 转为 II,String,int转为 Ljava/lang/String;I。*/ public static String toAsmType(final Class<?>[] classType) { String returnString = ""; for (Class<?> c : classType) { returnString += ASMEngineTools.toAsmType(c); } ; return returnString; } /**获取方法的Signature描述信息。*/ public static String toAsmSignature(Method targetMethod) { class MoreType { String name = null; Class<?> paramClass = null; TypeVariable<?> paramType = null; } // StringBuffer signature = new StringBuffer(); { //Step:1 Class<?>[] pTypeArray = targetMethod.getParameterTypes(); MoreType[] mTypeList = new MoreType[pTypeArray.length]; for (int i = 0; i < pTypeArray.length; i++) { Class<?> pType = pTypeArray[i]; MoreType mtype = new MoreType(); mtype.paramClass = pType; mTypeList[i] = mtype; } //Step:2 java.lang.reflect.Type[] gTypeArray = targetMethod.getGenericParameterTypes(); for (int i = 0; i < gTypeArray.length; i++) { java.lang.reflect.Type gType = gTypeArray[i]; if (gType instanceof TypeVariable) { mTypeList[i].name = ((TypeVariable<?>) gType).getName(); mTypeList[i].paramType = (TypeVariable<?>) gType; } } //Step:3 java.lang.reflect.Type[] tTypeArray = targetMethod.getTypeParameters(); for (int i = 0; i < tTypeArray.length; i++) { if (i == 0) { signature.append("<"); } // TypeVariable<?> tType = (TypeVariable<?>) tTypeArray[i]; String tName = tType.getName(); for (int j = 0; j < mTypeList.length; j++) { if (tName.equals(mTypeList[j].name)) { signature.append(tName); if (mTypeList[j].paramClass.isInterface()) { signature.append("::"); } else { signature.append(":"); } // for (java.lang.reflect.Type atType : mTypeList[j].paramType.getBounds()) { getTypeVarStr(signature, atType); } } } // if (i == tTypeArray.length - 1) { signature.append(">"); } } //Step:4 signature.append("("); for (int i = 0; i < mTypeList.length; i++) { MoreType mType = mTypeList[i]; if (mType.name != null) { signature.append(String.format("T%s;", mType.name)); } else { signature.append(toAsmType(mType.paramClass)); } } signature.append(")"); //Step:5 signature.append(toAsmType(targetMethod.getReturnType())); } // if (signature.length() == 0) { return null; } return signature.toString(); } private static StringBuffer getTypeVarStr(StringBuffer atString, java.lang.reflect.Type type) { // if (type instanceof TypeVariable) { TypeVariable<?> paramType = (TypeVariable<?>) type; atString.append("T" + paramType.getName() + ";"); } else if (type instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) type; atString.append("L" + replaceClassName((Class<?>) paramType.getRawType())); atString.append("<"); for (java.lang.reflect.Type atType : paramType.getActualTypeArguments()) { getTypeVarStr(atString, atType); } atString.append(">"); atString.append(";"); } else if (type instanceof Class<?>) { Class<?> paramType = (Class<?>) type; atString.append(toAsmType(paramType)); } else if (type instanceof WildcardType) { WildcardType paramType = (WildcardType) type; java.lang.reflect.Type[] upperType = paramType.getUpperBounds();//上边界 java.lang.reflect.Type[] lowerType = paramType.getLowerBounds();//下边界 if (lowerType.length == 0 && upperType.length != 0) { atString.append("+"); for (java.lang.reflect.Type atType : upperType) { getTypeVarStr(atString, atType); } } else if (lowerType.length != 0 && upperType.length != 0) { atString.append("-"); for (java.lang.reflect.Type atType : lowerType) { getTypeVarStr(atString, atType); } } else { throw new RuntimeException("Generic format error."); } } else if (type instanceof GenericArrayType) { //System.out.println(); } // return atString; } /**获取方法的ASM格式描述信息。*/ public static String toAsmFullDesc(Method method) { StringBuffer str = new StringBuffer(); str.append(method.getName()); str.append("("); str.append(toAsmType(method.getParameterTypes())); str.append(")"); Class<?> returnType = method.getReturnType(); if (returnType == void.class) { str.append("V"); } else { str.append(toAsmType(returnType)); } return str.toString(); } /**获取方法的ASM格式描述信息。*/ public static String toAsmDesc(Method method) { StringBuffer str = new StringBuffer(); str.append("("); str.append(toAsmType(method.getParameterTypes())); str.append(")"); Class<?> returnType = method.getReturnType(); if (returnType == void.class) { str.append("V"); } else { str.append(toAsmType(returnType)); } return str.toString(); } /** * 将IIIILjava/lang/Integer;F形式的ASM类型表述分解为数组。 * 测试字符串IIIILjava/lang/Integer;F[[[ILjava/lang.Boolean; -> * ["I", "I", "I", "I", "Ljava/lang/Integer;", "F", "[[[I", "Ljava/lang.Boolean"] * */ public static String[] splitAsmType(final String asmTypes) { class AsmTypeRead { StringReader sread = null; public AsmTypeRead(final String sr) { this.sread = new StringReader(sr); } /** 读取到下一个分号为止或者结束为止。*/ private String readToSemicolon() throws IOException { String res = ""; while (true) { int strInt = this.sread.read(); if (strInt == -1) { return res; } else if ((char) strInt == ';') { return res + ';'; } else { res += (char) strInt; } } } /** 读取一个类型 */ private String readType() throws IOException { int strInt = this.sread.read(); if (strInt == -1) { return ""; } switch ((char) strInt) { case '['://array return '[' + this.readType(); case 'L'://Object return 'L' + this.readToSemicolon(); default: return String.valueOf((char) strInt); } } /** 读取所有类型 */ public String[] readTypes() throws IOException { ArrayList<String> ss = new ArrayList<String>(0); while (true) { String s = this.readType(); if ("".equals(s)) { break; } else { ss.add(s); } } String[] res = new String[ss.size()]; ss.toArray(res); return res; } } try { return new AsmTypeRead(asmTypes).readTypes();// IIIILjava/lang/Integer;F[[[Ljava/util/Date; } catch (Exception e) { throw new RuntimeException("不合法的ASM类型desc。"); } } //======================================================================================================================= /**将类名转换为asm类名。*/ public static String replaceClassName(final Class<?> targetClass) { return targetClass.getName().replace(".", "/"); } /**通过位运算决定check是否在data里。*/ public static boolean checkIn(final int data, final int check) { int or = data | check; return or == data; } /**将一个Ljava/lang/Object;形式的字符串转化为java/lang/Object形式。*/ public static String asmTypeToType(final String asmType) { if (asmType.charAt(0) == 'L') { return asmType.substring(1, asmType.length() - 1); } else { return asmType; } } }