Java 不安全的defineAnonymousClass和ClassLoader之间的不同行为

Java 不安全的defineAnonymousClass和ClassLoader之间的不同行为,java,classloader,java-bytecode-asm,bytecode-manipulation,dynamic-class-loaders,Java,Classloader,Java Bytecode Asm,Bytecode Manipulation,Dynamic Class Loaders,我使用classloader和Unsafe::definedanymous()加载生成的字节码[]。classLoader.loadClass()返回的类的使用成功,而使用c.getMethod()返回的类失败,其中c=Unsafe.defineAnonymousClass()API。那么生成的字节码是错误的吗 我的代码: MainInliner loader = new MainInliner(); Class<?> c =null;

我使用classloader和Unsafe::definedanymous()加载生成的字节码[]。classLoader.loadClass()返回的类的使用成功,而使用
c.getMethod()
返回的类失败,其中
c=Unsafe.defineAnonymousClass()
API。那么生成的字节码是错误的吗

我的代码:

        MainInliner loader = new MainInliner();
        Class<?> c =null;
        byte[] bytes = ...
        if(args[0].equals("0")){
            c = loader.loadClass(name, bytes, 0, bytes.length);  // Classloader.loadClass.
        }else{
            c = Unsafe.defineAnonymousClass(Hoster, bytes, null);
        }

        Method m = c.getMethod("main", new Class<?>[] { String[].class    });
生成的字节码是:

 public void test(int, int);
    flags: ACC_PUBLIC
    Code:
      stack=5, locals=10, args_size=3
         0: iload_1       
         1: i2l   

         2: aload_0       
         3: getfield      #14                 // Field _callee:Lcode/sxu/asm/example/Callee;
         6: iload_1       
         7: iload_2       
         8: istore_3      
         9: istore        4
        11: astore        5
        13: lstore        6

        15: aload         5
        17: getfield      #42                 // Field code/sxu/asm/example/Callee._a:Ljava/lang/String;
        20: invokevirtual #48                 // Method java/lang/String.length:()I
        23: aload         5
        25: getfield      #51                 // Field code/sxu/asm/example/Callee._b:Ljava/lang/String;
        28: invokevirtual #48                 // Method java/lang/String.length:()I
        31: iadd          
        32: istore        8
        34: iload         8
        36: istore        9
        38: lload         6
        40: iload         9
        42: goto          45


        45: i2l           
        46: lsub          
        47: lstore_3        //r..

        48: iload_1       

        49: aload_0       
        50: getfield      #14                 // Field _callee:Lcode/sxu/asm/example/Callee;
        53: iload_2       
        54: iconst_0      
        55: istore_3      
        56: istore        4
        58: astore        5
        60: istore        6   //The backup stack bottom variable.

        62: aload         5
        64: getfield      #42                 // Field code/sxu/asm/example/Callee._a:Ljava/lang/String;
        67: invokevirtual #48                 // Method java/lang/String.length:()I
        70: aload         5
        72: getfield      #51                 // Field code/sxu/asm/example/Callee._b:Ljava/lang/String;
        75: invokevirtual #48                 // Method java/lang/String.length:()I
        78: iadd          
        79: istore        7
        81: iload         7
        83: istore        8
        85: iload         6     //Push back 6
        87: iload         8     //Repush 8
        89: goto          92
                                //return calculate()
        92: iadd          
        93: istore        5
        95: getstatic     #61                 // Field java/lang/System.out:Ljava/io/PrintStream;
        98: lload_3       
        99: invokevirtual #67                 // Method java/io/PrintStream.println:(J)V
       102: return        
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
              15      30     5  this   Lcode/sxu/asm/example/Callee;
              15      30     4     t   I
              15      30     3     p   I
              34      11     8   tmp   I
              62      30     5  this   Lcode/sxu/asm/example/Callee;
              62      30     4     t   I
              62      30     3     p   I
              81      11     7   tmp   I
               0     103     0  this   Lcode/sxu/asm/example/Caller;
               0     103     1     a   I
               0     103     2     b   I
              48      55     3     r   J
              95       8     5     c   I
      LineNumberTable:
        line 19: 0
        line 16: 15
        line 23: 34
        line 21: 48
        line 16: 62
        line 23: 81
        line 23: 95
        line 30: 102
      StackMapTable: number_of_entries = 2
           frame_type = 255 /* full_frame */
          offset_delta = 45
          locals = [ class code/sxu/asm/example/Caller, int, int, int, int, class code/sxu/asm/example/Callee, long, int, int ]
          stack = [ long, int ]
           frame_type = 255 /* full_frame */
          offset_delta = 46
          locals = [ class code/sxu/asm/example/Caller, int, int, int, int, class code/sxu/asm/example/Callee, int, int, int, int ]
          stack = [ int, int ]

}
此字节码对应于内联的被调用方方法

我检查了这个字节码序列,似乎没有错误。错误消息中的变量3出现4次,其中:

8: istore_3        //Popo up existing parameters for inlining. 
47: lstore_3        //r. The local variable in the Caller method
55: istore_3        // Similiar to the label 8, pops stack paras to local variable. 
98: lload_3         //Println parameter
相应的方法是:

public class Caller{
public void test(int a, int b){
    long r = (long)a- _callee.calculate(a, b);
    int c = a +_callee.calculate(b, 0);
    System.out.println(r);
}
}


loader.loadClass(字节)
是什么意思?没有这样的
ClassLoader.loadClass(byte[])
方法。您是如何生成字节码的?您是否从现有方法开始并对其进行了修改?是的。字节码是基于调用者和被调用者的类生成的,使用ASM库
loader.loadClass(名称、字节、0、字节、长度)
?没有这样的
ClassLoader.loadClass(字符串,字节[],int,int)
方法。这里输入错误。loadClass(字符串)将最终调用defineClass(名称、字节、0、长度)。我自己的问题已经有了答案。变量索引错误,因为
55:istore_3
出于性能原因,我没有建议使用它。问题是,由于反射不兼容的自优化,一些实现存在问题。Read,在一些成功的调用之后,
方法
将尝试通过编译访问器类来优化自身,但由于其他类无法访问匿名类,因此在调用
调用
时,您会突然收到
错误
s。这可能发生在20次左右的调用之后。如前所述,这取决于实现,因此是jre版本。这就是为什么我说俄罗斯轮盘赌。
public class Caller{
public void test(int a, int b){
    long r = (long)a- _callee.calculate(a, b);
    int c = a +_callee.calculate(b, 0);
    System.out.println(r);
}
  public class Callee{
    public int calculate(int t, int p){
        int tmp=_a.length()+_b.length();
        return tmp;
    }}