WEB开发网
开发学院软件开发Java Java 编程的动态性,第 7 部分: 用 BCEL 设计字节... 阅读

Java 编程的动态性,第 7 部分: 用 BCEL 设计字节码

 2010-03-18 00:00:00 来源:WEB开发网   
核心提示: 您可能会奇怪为什么在开始参数大小计算时要检查方法是否是静态的,如果是静态的,Java 编程的动态性,第 7 部分: 用 BCEL 设计字节码(7),将堆栈帧槽初始化为零(不是静态正好相反),这种方式与 Java 如何处理方法调用有关,然后 for 循环生成将所有调用参数值拷贝到堆栈中的代码, c

您可能会奇怪为什么在开始参数大小计算时要检查方法是否是静态的,如果是静态的,将堆栈帧槽初始化为零(不是静态正好相反)。这种方式与 Java 如何处理方法调用有关。对于非静态的方法,每次调用的第一个(隐藏的)参数是目标对象的 this 引用,在计算堆栈帧中完整参数集大小时我要考虑到这点。

清单 4. 设置包装的调用

// compute the size of the calling parameters 
Type[] types = methgen.getArgumentTypes(); 
int slot = methgen.isStatic() ? 0 : 1; 
for (int i = 0; i < types.length; i++) { 
  slot += types[i].getSize(); 
} 
   
// save time prior to invocation 
ilist.append(ifact.createInvoke("java.lang.System", 
  "currentTimeMillis", Type.LONG, Type.NO_ARGS, 
  Constants.INVOKESTATIC)); 
ilist.append(InstructionFactory.createStore(Type.LONG, slot)); 

清单 5 显示了生成对包装方法的调用并保存结果(如果有的话)的代码。这段代码的第一部分再次检查方法是否是静态的。如果方法不是静态的,那么就生成将 this 对象引用装载到堆栈中的代码,同时设置方法调用类型为 virtual (而不是 static )。然后 for 循环生成将所有调用参数值拷贝到堆栈中的代码, createInvoke() 方法生成对包装的方法的实际调用,最后 if 语句将结果值保存到位于堆栈帧中的另一个局部变量中(如果结果类型不是 void )。

清单 5. 调用包装的方法

// call the wrapped method 
int offset = 0; 
short invoke = Constants.INVOKESTATIC; 
if (!methgen.isStatic()) { 
  ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0)); 
  offset = 1; 
  invoke = Constants.INVOKEVIRTUAL; 
} 
for (int i = 0; i < types.length; i++) { 
  Type type = types[i]; 
  ilist.append(InstructionFactory.createLoad(type, offset)); 
  offset += type.getSize(); 
} 
Type result = methgen.getReturnType(); 
ilist.append(ifact.createInvoke(cname, 
  iname, result, types, invoke)); 
   
// store result for return later 
if (result != Type.VOID) { 
  ilist.append(InstructionFactory.createStore(result, slot+2)); 
} 

上一页  2 3 4 5 6 7 8 9 10  下一页

Tags:Java 编程 动态性

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接