<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-204  評論-149  文章-0  trackbacks-0

    有了前幾篇關于BCEL的使用,現在API轉換的問題其實很簡單了
    實際API轉換要做的比這個例子要復雜些,涉及到包名,類名,方法名稱等的變化。把常量池變化搞清楚就夠了

    假如這是APIa中的一個類
    實際只提供APIa的jar包,不提供源代碼

    package one.api;

    public class MyAPITest {
        
        
    public int add(String a,String b){
            
    return new Integer(a).intValue()+new Integer(b).intValue();
        }


    }


    如下是APIb的相對應的類,注意兩個APIa提供的類層次結構,類的名稱已經方法的名稱是一致的

    package one.api;

    public class MyAPITest {
        
        
    public int add(int a,int b){
            
    return a+b;
        }


    }


    現在有一個應用程序使用的是APIa的類來寫的,并且只提供classes文件,
    假如現在把此應用程序放在另一臺機器上運行,但是此機器上只能提供APIb的jar包,要想此應用程序能夠在此機器上運行,則要修改應用程序的classes字節碼。
    應用程序的代碼如下:
    package client;

    import one.api.MyAPITest;

    public class ClientTest {

        
    /**
         * 
    @param args
         
    */

        
    public static void main(String[] args) {
            
            MyAPITest sb = new MyAPITest();
            int result = sb.add("1", "2");

            System.out.println(result);
            

        }

        
        
    public int mytest(String a,String b){
            MyAPITest sb = new MyAPITest();
            int result = sb.add(a, b);

            
    return result;
        }


    }


    則要調用sb.add(a, b);的地方將方法的參數改為整型的
    本來的指令序列如下
     ldc  "1" 
     ldc  "2" 
     invokevirtual one.api.MyAPITest.add (Ljava/lang/String;Ljava/lang/String;)I

    則將字節碼的內容加入
     ldc  "1" 
     invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
     ldc  "2" 
     invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
     invokevirtual one.api.MyAPITest.add (II)I
    紅色的指令是將操作數棧的棧頂元素由字符串改變為整型
    并且還需要把調用的方法的新的方法簽名加入到常量池Constant_Pool中
    1,這個在原來的指令序列中插入轉換指令需要插入的地方,但方法的參數比較明確時如add("1","2")或者add(s1,s2),s1,s2是局部變量,這個插入的地方比較好早。但是當方法的參數是直接調用其他方法的而產生返回結果時,還需要往指令前找其他方法的調用指令以及這個其他方法有幾個參數,在這個其他方法調用后將這個其他方法的返回結果進行整型轉換。
    說的有的亂,假如main方法中為如下時
        public static void main(String[] args) {
            
            MyAPITest sb 
    = new MyAPITest();
            
            
    int result = sb.add("1""2");
            System.out.println(result);
            
            String temp = "999";
            int resultone = sb.add(temp, "33");
            System.out.println(resultone);

            
            
    int resulttwo = sb.add(String.valueOf("1"), String.valueOf("2"));
            System.out.println(resulttwo);

            
    int resultthree = sb.add(StringUtil.createStringOne("111"),"333");
            System.out.println(resultthree);
            
            
    int resultfour = sb.add(StringUtil.createStringTwo("23", "34"),StringUtil.createStringThree("12", "23", "34"));
            System.out.println(resultfour);

            
            
    int resultfive = sb.add(StringUtil.createStringTwo(StringUtil.createStringOne("88"), "34"),StringUtil.createStringThree("12", "23", "34"));
            System.out.println(resultfive);

        }

    上面的指令序列為如下:
    完整的code.toString的信息
    public static void main(String[] args)
    Code(max_stack 
    = 5, max_locals = 9, code_length = 153)
    0:    new        <one.api.MyAPITest> (16)
    3:    dup
    4:    invokespecial    one.api.MyAPITest.<init> ()V (18)
    7:    astore_1
    8:    aload_1
    9:    ldc        "1" (19)
    11:   ldc        "2" (21)
    13:   invokevirtual    one.api.MyAPITest.add (Ljava/lang/String;Ljava/lang/String;)I (23)
    16:   istore_2
    17:   getstatic        java.lang.System.out Ljava/io/PrintStream; (27)
    20:   iload_2
    21:   invokevirtual    java.io.PrintStream.println (I)V (33)
    24:   ldc        "999" (39)
    26:   astore_3
    27:   aload_1
    28:   aload_3
     invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
    29:   ldc        "33" (41)
    invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
    31:   invokevirtual    one.api.MyAPITest.add (Ljava/lang/String;Ljava/lang/String;)I (23)

    34:   istore        %4
    36:   getstatic        java.lang.System.out Ljava/io/PrintStream; (27)
    39:   iload        %4
    41:   invokevirtual    java.io.PrintStream.println (I)V (33)
    44:   aload_1
    45:   ldc        "1" (19)
    47:   invokestatic    java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (43)
    50:   ldc        "2" (21)
    52:   invokestatic    java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (43)
    55:   invokevirtual    one.api.MyAPITest.add (Ljava/lang/String;Ljava/lang/String;)I (23)
    58:   istore        %5
    60:   getstatic        java.lang.System.out Ljava/io/PrintStream; (27)
    63:   iload        %5
    65:   invokevirtual    java.io.PrintStream.println (I)V (33)
    68:   aload_1
    69:   ldc        "111" (49)
    71:   invokestatic    client.StringUtil.createStringOne (Ljava/lang/String;)Ljava/lang/String; (51)
    74:   ldc        "333" (57)
    76:   invokevirtual    one.api.MyAPITest.add (Ljava/lang/String;Ljava/lang/String;)I (23)
    79:   istore        %6
    81:   getstatic        java.lang.System.out Ljava/io/PrintStream; (27)
    84:   iload        %6
    86:   invokevirtual    java.io.PrintStream.println (I)V (33)
    89:   aload_1
    90:   ldc        "23" (59)
    92:   ldc        "34" (61)
    94:   invokestatic    client.StringUtil.createStringTwo (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; (63)
    invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
    97:   ldc        "12" (67)
    99:   ldc        "23" (59)
    101:  ldc        "34" (61)
    103:  invokestatic    client.StringUtil.createStringThree (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; (69)
    invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
    106:  invokevirtual    one.api.MyAPITest.add (Ljava/lang/String;Ljava/lang/String;)I (23)
    109:  istore        %7
    111:  getstatic        java.lang.System.out Ljava/io/PrintStream; (27)
    114:  iload        %7
    116:  invokevirtual    java.io.PrintStream.println (I)V (33)
    119:  aload_1
    120:  ldc        "88" (73)
    122:  invokestatic    client.StringUtil.createStringOne (Ljava/lang/String;)Ljava/lang/String; (51)
    125:  ldc        "34" (61)
    127:  invokestatic    client.StringUtil.createStringTwo (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; (63)
    invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
    130:  ldc        "12" (67)
    132:  ldc        "23" (59)
    134:  ldc        "34" (61)
    136:  invokestatic    client.StringUtil.createStringThree (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; (69)
    invokestatic java.lang.Integer.parseInt(Ljava/lang/String;)I
    139:  invokevirtual    one.api.MyAPITest.add (Ljava/lang/String;Ljava/lang/String;)I (23)
    142:  istore        %8
    144:  getstatic        java.lang.System.out Ljava/io/PrintStream; (27)
    147:  iload        %8
    149:  invokevirtual    java.io.PrintStream.println (I)V (33)
    152:  return

    Attribute(s) 
    = 
    LineNumber(
    012), LineNumber(814), LineNumber(1715), LineNumber(2417), 
    LineNumber(
    2718), LineNumber(3619), LineNumber(4421), LineNumber(6022), 
    LineNumber(
    6824), LineNumber(8125), LineNumber(8927), LineNumber(11128), 
    LineNumber(
    11930), LineNumber(14431), LineNumber(15232)
    LocalVariable(start_pc 
    = 0, length = 153, index = 0:String[] args)
    LocalVariable(start_pc 
    = 8, length = 145, index = 1:one.api.MyAPITest sb)
    LocalVariable(start_pc 
    = 17, length = 136, index = 2:int result)
    LocalVariable(start_pc 
    = 27, length = 126, index = 3:String temp)
    LocalVariable(start_pc 
    = 36, length = 117, index = 4:int resultone)
    LocalVariable(start_pc 
    = 60, length = 93, index = 5:int resulttwo)
    LocalVariable(start_pc 
    = 81, length = 72, index = 6:int resultthree)
    LocalVariable(start_pc 
    = 111, length = 42, index = 7:int resultfour)
    LocalVariable(start_pc 
    = 144, length = 9, index = 8:int resultfive)

    看int resultone = sb.add(temp, "33");
    要找對應的這個插入地方,首先需要判斷第一個參數是局部變量使用的aload指令,第二個參數是直接LDC的
    而對于
    int resultfour = sb.add(StringUtil.createStringTwo("23", "34"),StringUtil.createStringThree("12", "23", "34"));
    add的參數都是由方法調用的,需要知道在調用add的指令前有幾個invokeXXX指令,然后判斷這些指令有幾個參數,然后選擇合適的地方來插入,總之要根據方法調用的參數個數往前找插入的地方,這個雖然可以實現,但是實現起來比較麻煩,不是一個好的辦法。
    2.我比較推崇的方法時,但調用add時,此時但卻操作棧的前幾個數肯定是add的參數,只需要對這些數進行轉換即可,但是要創建額外的局部變量來保存中間結果,當參數都轉換完時,在把這些自己創建的局部變量壓入操作棧中,這些操作都在add所對應的invokevirtual指令前,當調用invokevirtual時,操作數棧的前幾個元素已經是整型了
    package transmit;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import org.apache.bcel.Constants;
    import org.apache.bcel.classfile.ClassParser;
    import org.apache.bcel.classfile.Constant;
    import org.apache.bcel.classfile.ConstantClass;
    import org.apache.bcel.classfile.ConstantFieldref;
    import org.apache.bcel.classfile.ConstantMethodref;
    import org.apache.bcel.classfile.ConstantNameAndType;
    import org.apache.bcel.classfile.ConstantPool;
    import org.apache.bcel.classfile.JavaClass;
    import org.apache.bcel.classfile.Method;
    import org.apache.bcel.generic.ClassGen;
    import org.apache.bcel.generic.ConstantPoolGen;
    import org.apache.bcel.generic.INVOKEVIRTUAL;
    import org.apache.bcel.generic.Instruction;
    import org.apache.bcel.generic.InstructionFactory;
    import org.apache.bcel.generic.InstructionHandle;
    import org.apache.bcel.generic.InstructionList;
    import org.apache.bcel.generic.LocalVariableGen;
    import org.apache.bcel.generic.MethodGen;
    import org.apache.bcel.generic.Type;

    public class ChangeUsingBcel {

        
    /*
         * 掃描StringBuilder的各個方法的指令序列,在其中找Invokexxxx指令,
         * 看此指令在常量池中引用的方法引用是否是要其前后加代碼的方法
         * 方法所在的類要一致,方法的名稱要一致,方法的簽名要一致
         * 
         
    */

        
        
    /**
         * 
         * 
    @param cgen 要被解析的類class文件
         * 
    @param classname 要被修改的方法所在的類名稱,若有包名,則為java/lang/Object類似的one/api/MyAPITest
         * 
    @param methodname 要被修改的方法的名稱add
         * 
    @param methodSignature 要被修改的方法的簽名(Ljava/lang/String;Ljava/lang/String;)I
         * 
         * Map.put(classname,list.add(map.put(
         
    */

        
    private static void modifyWrapper(ClassGen cgen,String classname,String methodname,String methodSignature){
            
            InstructionFactory ifact 
    = new InstructionFactory(cgen);
            ConstantPoolGen pgen 
    = cgen.getConstantPool();
            
            ConstantPool pool 
    = pgen.getConstantPool();
            
            
            
            
    //留作它用
            Map<String,List> map = new HashMap<String,List>();
            List list 
    = new ArrayList();
            list.add((
    new HashMap()).put(methodname, methodSignature));
            map.put(classname, list);
            
            
    /*
             * 先查查此類的常量池中是否有 MyAPITest的引用
             *常量池的0號索引沒有使用
             
    */

            Map classrefMap 
    = new HashMap();
            Map methodrefMap 
    = new HashMap();
            Map fieldrefMap 
    = new HashMap();
            
            
            
            System.out.println(
    "pool.getLength()   "+pool.getLength());//1024不是實際的條數
            Constant[] constants = pool.getConstantPool();
            System.out.println(
    "constants.length   "+constants.length);//1024
            for(int cN=1;cN<constants.length;cN++){
                Constant tempCon 
    = pool.getConstant(cN);
                
    if(tempCon!=null && tempCon.getTag()==Constants.CONSTANT_Class){
                    ConstantClass tempConClass 
    = (ConstantClass)tempCon;
                    String classSignature 
    = tempConClass.getBytes(pool);// one/api/MyAPITest
                    if(classSignature.equals("one/api/MyAPITest")){
                        
    //池中有此class的引用,然后判斷方法引用或域引用的class_index為此類的index
                        int class_index = cN;
                        classrefMap.put(class_index, classSignature);
                        
    /*
                         * 再次遍歷常量池找
                         
    */

                        
    for(int cN2=1;cN2<constants.length;cN2++){
                            Constant temp 
    = pool.getConstant(cN2);
                            System.out.println(temp);
                            
    if(temp!=null && temp.getTag()==Constants.CONSTANT_Methodref){
                                ConstantMethodref cmr 
    = (ConstantMethodref)temp;
                                
    if(cmr.getClassIndex()==class_index){
                                    ConstantNameAndType cnat 
    = (ConstantNameAndType)pool.getConstant(cmr.getNameAndTypeIndex());
                                    System.out.println(
    "方法的名稱 "+cnat.getName(pool));
                                    System.out.println(
    "方法的簽名 "+cnat.getSignature(pool));
                                    methodrefMap.put(cnat.getName(pool), cnat.getSignature(pool));
    //                                pool.constantToString(index, tag)
    //                                pool.constantToString(c)
                                }

                            }

                            
    if(temp!=null && temp.getTag()==Constants.CONSTANT_Fieldref){
                                ConstantFieldref cfr 
    = (ConstantFieldref)temp;
                                
    if(cfr.getClassIndex()==class_index){
                                    ConstantNameAndType cnat 
    = (ConstantNameAndType)pool.getConstant(cfr.getNameAndTypeIndex());
                                    System.out.println(
    "引用的域的名稱 "+cnat.getName(pool));
                                    System.out.println(
    "引用的域的簽名 "+cnat.getSignature(pool));
                                    fieldrefMap.put(cnat.getName(pool), cnat.getSignature(pool));
                                }

                            }

                        }

                        
                    }

                }

            }

            
            
            
    /*
             * 分析類的各個方法,在各個方法中找出調用語句
             
    */

            
            String cname 
    = cgen.getClassName();
            
            
            
            Method[] methods 
    = cgen.getMethods();
            
    for(int i=0;i<methods.length;i++){
                Method tempMethod 
    = methods[i];
                
                MethodGen tempMethodGen 
    = new MethodGen(tempMethod,cname,pgen);
                
                InstructionList tempList 
    = tempMethodGen.getInstructionList();
                System.out.println(
    "tempList.getLength()            "+tempList.getLength());;
                
    //Instruction[] tempInstructions = tempList.getInstructions();
                InstructionHandle[] tempInHandles = tempList.getInstructionHandles();
                System.out.println(
    "tempInHandles.length            "+tempInHandles.length);
                
                
    for(int j=0;j<tempInHandles.length;j++){
                    InstructionHandle ihandle 
    = tempInHandles[j];
                    Instruction nowInstruction 
    = ihandle.getInstruction();
                    
    if(nowInstruction.getOpcode()==Constants.INVOKEVIRTUAL){
                        INVOKEVIRTUAL invokeVirtual 
    = (INVOKEVIRTUAL)nowInstruction;
                        ConstantMethodref cmr 
    = (ConstantMethodref)pgen.getConstant(invokeVirtual.getIndex());
                        
                        
                        
                        ConstantClass cc 
    = (ConstantClass)pgen.getConstant(cmr.getClassIndex());
                        String nowClassName 
    = cc.getBytes(pgen.getConstantPool());
                        ConstantNameAndType cnt 
    = (ConstantNameAndType)pgen.getConstant(cmr.getNameAndTypeIndex());
                        String nowMethodName 
    = cnt.getName(pgen.getConstantPool());
                        String nowMethodSignature 
    = cnt.getSignature(pgen.getConstantPool());
                        
                        
    //判斷此方法的所屬的類,方法的名稱,方法的簽名是否與所要加的一致(I)Ljava/lang/String;
                        
    //不加方法簽名的話,當類中有重載方法時不好辦,加的話,if中當遇到第一個時又把其給改掉了,后面的invokexxx的方法簽名是改后的了,因此這樣的簽名的方法也要加上指令
                        if(nowClassName.equals(classname) && nowMethodName.equals(methodname) && (nowMethodSignature.equals(methodSignature)||(nowMethodSignature.equals("(II)I")))){
                            
                            cgen.removeMethod(tempMethodGen.getMethod());
                            
                            InstructionList addList 
    = new InstructionList();
                            addList.append(ifact.createInvoke(
    "java.lang.Integer""parseInt", Type.INT, new Type[]{Type.STRING}, Constants.INVOKESTATIC));
                            
    //這個局部變量的作用范圍如何確定,還是簡簡單單的設置成null表示從開放開始到結束
                            LocalVariableGen lvg = tempMethodGen.addLocalVariable("paramTwoint", Type.INT, nullnull);
                            
    //把當前棧的整型結果保存到局部變量中
                            addList.append(ifact.createStore(Type.INT, lvg.getIndex()));
                            
                            
    //再轉換第一個字符參數
                            addList.append(ifact.createInvoke("java.lang.Integer""parseInt", Type.INT, new Type[]{Type.STRING}, Constants.INVOKESTATIC));
    //                        LocalVariableGen lvg2 = tempMethodGen.addLocalVariable("paramOneint", Type.INT, null, null);
    //                        ifact.createStore(Type.INT, lvg2.getIndex());
    //                        
    //                        //再把兩個整型局部局部加到棧中
    //                        ifact.createLoad(Type.INT, lvg2.getIndex());
                            addList.append(ifact.createLoad(Type.INT, lvg.getIndex()));
                            
                            
    //將指令插入到invokeVirtual之前
                            tempList.insert(ihandle, addList);
                            
                            
    //修改方法的簽名到(II)I
                            
    //可以保留原來的Methodref,使用addMethodref來添加新的methodref
                            
    //原來的methodref根本就沒有用,其實可以從常量池刪除調
    //                        int newMethodIndex = pgen.addMethodref("one.api.MyAPITest", "add", "(II)I");
    //                        invokeVirtual.setIndex(newMethodIndex);
                            
                            
                            
    //在if語句中改的話,后面的調用都不會被加代碼了
                            
    //或者自己加一個NameAndType這樣還避免沖突,然后把新的下標賦給原來的方法引用
                            int new_name_and_type_index = pgen.addNameAndType("add""(II)I");
                            cmr.setNameAndTypeIndex(new_name_and_type_index);
                            
    //假如方法的class_index也發生了變化,則也可以
    //                        int new_class_index = pgen.addClass(str);
    //                        cmr.setClassIndex(class_index);
                            
                            
                            
    //finalize the construted method
                            tempMethodGen.stripAttributes(false);
                            tempMethodGen.setMaxStack();
                            tempMethodGen.setMaxLocals();

                            cgen.addMethod(tempMethodGen.getMethod());
                            
                            System.out.println(tempMethodGen.getInstructionList());
                            System.out.println();
                            System.out.println();
                            
                            
                        }

                        
                        
    if(nowClassName.equals(classname) && nowMethodName.equals(""&& nowMethodSignature.equals("")){
                            
    //此類中的其他方法的改動
                            
    //
                        }

                        
                        
                    }

                    
                    
    //此類中的使用到classname類中的域
                    if(nowInstruction.getOpcode()==Constants.GETFIELD){
                        
    //..
                    }

                }

                
    //            tempList.setPositions();
    //            tempList.findHandle(pos);
                
            }

                
        }


        
    /**
         * 
    @param args
         
    */

        
    public static void main(String[] args) {
            
            args[
    0]="D:\\java to eclipse\\javaeclipsestudy\\workspace\\BCELTest\\bin\\client\\ClientTest.class";
            
            
    if(args.length==1 && args[0].endsWith(".class")){
                
    try{
                    JavaClass jclas 
    = new ClassParser(args[0]).parse();
                    
                    ClassGen cgen 
    = new ClassGen(jclas);
                    
                    modifyWrapper(cgen,
    "one/api/MyAPITest","add","(Ljava/lang/String;Ljava/lang/String;)I");
                    
                    
                    cgen.getJavaClass().dump(args[
    0]);
                }
    catch(Exception e){
                    e.printStackTrace();
                }

            }
    else{
                System.out.println(
    "usage: class-file");
            }


        }



    }


    改變字節碼的片段
    129:  aload_1
    130:  ldc  "23" (59)
    132:  ldc  "34" (61)
    134:  invokestatic client.StringUtil.createStringTwo (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; (63)
    137:  ldc  "12" (67)
    139:  ldc  "23" (59)
    141:  ldc  "34" (61)
    143:  invokestatic client.StringUtil.createStringThree (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; (69)
    146:  invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (98)
    149:  istore  %13
    151:  invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (98)
    154:  iload  %13
    156:  invokevirtual one.api.MyAPITest.add (II)I (23)

    posted on 2009-08-16 19:30 Frank_Fang 閱讀(1808) 評論(2)  編輯  收藏 所屬分類: bcel javassist

    評論:
    # re: API轉換的問題的解決 2009-08-16 23:38 | Frank_Fang
    藍色的指令是采用方法1所加的位置,這樣做不太方便
      回復  更多評論
      
    # re: API轉換的問題的解決 2009-08-17 21:54 | Frank_Fang
    使用反編譯工具根據生成的class文件生成的java文件
    // Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
    // Jad home page: http://kpdus.tripod.com/jad.html
    // Decompiler options: packimports(3) fieldsfirst ansi space
    // Source File Name: ClientTest.java

    package client;

    import java.io.PrintStream;
    import one.api.MyAPITest;

    // Referenced classes of package client:
    // StringUtil

    public class ClientTest
    {

    public ClientTest()
    {
    }

    public static void main(String args[])
    {
    MyAPITest sb = new MyAPITest();
    int paramTwoint = Integer.parseInt("2");
    int result = sb.add(Integer.parseInt("1"), paramTwoint);
    System.out.println(result);
    String temp = "999";
    int paramTwoint = Integer.parseInt("33");
    int resultone = sb.add(Integer.parseInt(temp), paramTwoint);
    System.out.println(resultone);
    int paramTwoint = Integer.parseInt(String.valueOf("2"));
    int resulttwo = sb.add(Integer.parseInt(String.valueOf("1")), paramTwoint);
    System.out.println(resulttwo);
    int paramTwoint = Integer.parseInt("333");
    int resultthree = sb.add(Integer.parseInt(StringUtil.createStringOne("111")), paramTwoint);
    System.out.println(resultthree);
    int paramTwoint = Integer.parseInt(StringUtil.createStringThree("12", "23", "34"));
    int resultfour = sb.add(Integer.parseInt(StringUtil.createStringTwo("23", "34")), paramTwoint);
    System.out.println(resultfour);
    int paramTwoint = Integer.parseInt(StringUtil.createStringThree("12", "23", "34"));
    int resultfive = sb.add(Integer.parseInt(StringUtil.createStringTwo(StringUtil.createStringOne("88"), "34")), paramTwoint);
    System.out.println(resultfive);
    }

    public int mytest(String a, String b)
    {
    MyAPITest sb = new MyAPITest();
    int paramTwoint = Integer.parseInt(b);
    int result = sb.add(Integer.parseInt(a), paramTwoint);
    return result;
    }
    }  回復  更多評論
      
    主站蜘蛛池模板: 永久免费在线观看视频| 狠狠入ady亚洲精品| 日日麻批免费40分钟无码| 亚洲深深色噜噜狠狠爱网站| 看免费毛片天天看| 亚洲第一视频在线观看免费| 精品一区二区三区免费毛片| 四虎影视永久免费视频观看| 一级片在线免费看| 亚洲色大成网站WWW久久九九| a国产成人免费视频| 亚洲高清在线观看| 亚州免费一级毛片| 亚洲夂夂婷婷色拍WW47| 免费国产综合视频在线看| 亚洲免费在线观看| 亚洲AV无码码潮喷在线观看| 69av免费视频| 亚洲国产精品无码观看久久| 亚洲?v无码国产在丝袜线观看| 九九免费观看全部免费视频| 亚洲AV无码AV男人的天堂| 在线观看无码AV网站永久免费| 亚洲aⅴ无码专区在线观看春色 | 四虎永久免费地址在线观看| 日韩在线视频线视频免费网站| 亚洲国产婷婷六月丁香| 久久午夜夜伦鲁鲁片免费无码影视 | 久久国产亚洲精品无码| 男人的好看免费观看在线视频| 精品久久久久亚洲| 亚洲精品国产精品乱码不99| 久久精品国产免费观看| 色天使亚洲综合一区二区| 国产AV无码专区亚洲A∨毛片| 国产h视频在线观看网站免费| 美女露隐私全部免费直播| 久久久久无码精品亚洲日韩 | 69成人免费视频| 人妖系列免费网站观看| 亚洲日韩中文字幕|