您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

MethodCall.java 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later.
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. */
  15. package javassist.expr;
  16. import javassist.*;
  17. import javassist.bytecode.*;
  18. import javassist.compiler.*;
  19. /**
  20. * Method invocation (caller-side expression).
  21. */
  22. public class MethodCall extends Expr {
  23. /**
  24. * Undocumented constructor. Do not use; internal-use only.
  25. */
  26. MethodCall(int pos, CodeIterator i, CtClass declaring, MethodInfo m) {
  27. super(pos, i, declaring, m);
  28. }
  29. private int getNameAndType(ConstPool cp) {
  30. String cname;
  31. int pos = currentPos;
  32. int c = iterator.byteAt(pos);
  33. int index = iterator.u16bitAt(pos + 1);
  34. if (c == INVOKEINTERFACE)
  35. return cp.getInterfaceMethodrefNameAndType(index);
  36. else
  37. return cp.getMethodrefNameAndType(index);
  38. }
  39. /**
  40. * Returns the method or constructor containing the method-call
  41. * expression represented by this object.
  42. */
  43. public CtBehavior where() { return super.where(); }
  44. /**
  45. * Returns the line number of the source line containing the
  46. * method call.
  47. *
  48. * @return -1 if this information is not available.
  49. */
  50. public int getLineNumber() {
  51. return super.getLineNumber();
  52. }
  53. /**
  54. * Returns the source file containing the method call.
  55. *
  56. * @return null if this information is not available.
  57. */
  58. public String getFileName() {
  59. return super.getFileName();
  60. }
  61. /**
  62. * Returns the class of the target object,
  63. * which the method is called on.
  64. */
  65. private CtClass getCtClass() throws NotFoundException {
  66. return thisClass.getClassPool().get(getClassName());
  67. }
  68. /**
  69. * Returns the class name of the target object,
  70. * which the method is called on.
  71. */
  72. public String getClassName() {
  73. String cname;
  74. ConstPool cp = getConstPool();
  75. int pos = currentPos;
  76. int c = iterator.byteAt(pos);
  77. int index = iterator.u16bitAt(pos + 1);
  78. if (c == INVOKEINTERFACE)
  79. cname = cp.getInterfaceMethodrefClassName(index);
  80. else
  81. cname = cp.getMethodrefClassName(index);
  82. return cname;
  83. }
  84. /**
  85. * Returns the name of the called method.
  86. */
  87. public String getMethodName() {
  88. ConstPool cp = getConstPool();
  89. int nt = getNameAndType(cp);
  90. return cp.getUtf8Info(cp.getNameAndTypeName(nt));
  91. }
  92. /**
  93. * Returns the called method.
  94. */
  95. public CtMethod getMethod() throws NotFoundException {
  96. return getCtClass().getMethod(getMethodName(), getMethodDesc());
  97. }
  98. private String getMethodDesc() {
  99. ConstPool cp = getConstPool();
  100. int nt = getNameAndType(cp);
  101. return cp.getUtf8Info(cp.getNameAndTypeDescriptor(nt));
  102. }
  103. /**
  104. * Returns the list of exceptions that the expression may throw.
  105. * This list includes both the exceptions that the try-catch statements
  106. * including the expression can catch and the exceptions that
  107. * the throws declaration allows the method to throw.
  108. */
  109. public CtClass[] mayThrow() {
  110. return super.mayThrow();
  111. }
  112. /**
  113. * Returns true if the called method is of a superclass of the current
  114. * class.
  115. */
  116. public boolean isSuper() {
  117. return iterator.byteAt(currentPos) == INVOKESPECIAL
  118. && !where().getDeclaringClass().getName().equals(getClassName());
  119. }
  120. /*
  121. * Returns the parameter types of the called method.
  122. public CtClass[] getParameterTypes() throws NotFoundException {
  123. return Descriptor.getParameterTypes(getMethodDesc(),
  124. thisClass.getClassPool());
  125. }
  126. */
  127. /*
  128. * Returns the return type of the called method.
  129. public CtClass getReturnType() throws NotFoundException {
  130. return Descriptor.getReturnType(getMethodDesc(),
  131. thisClass.getClassPool());
  132. }
  133. */
  134. /**
  135. * Replaces the method call with the bytecode derived from
  136. * the given source text.
  137. *
  138. * <p>$0 is available even if the called method is static.
  139. *
  140. * @param statement a Java statement.
  141. */
  142. public void replace(String statement) throws CannotCompileException {
  143. ConstPool constPool = getConstPool();
  144. int pos = currentPos;
  145. int index = iterator.u16bitAt(pos + 1);
  146. String classname, methodname, signature;
  147. int opcodeSize;
  148. int c = iterator.byteAt(pos);
  149. if (c == INVOKEINTERFACE) {
  150. opcodeSize = 5;
  151. classname = constPool.getInterfaceMethodrefClassName(index);
  152. methodname = constPool.getInterfaceMethodrefName(index);
  153. signature = constPool.getInterfaceMethodrefType(index);
  154. }
  155. else if (c == INVOKESTATIC
  156. || c == INVOKESPECIAL || c == INVOKEVIRTUAL) {
  157. opcodeSize = 3;
  158. classname = constPool.getMethodrefClassName(index);
  159. methodname = constPool.getMethodrefName(index);
  160. signature = constPool.getMethodrefType(index);
  161. }
  162. else
  163. throw new CannotCompileException("not method invocation");
  164. Javac jc = new Javac(thisClass);
  165. ClassPool cp = thisClass.getClassPool();
  166. CodeAttribute ca = iterator.get();
  167. try {
  168. CtClass[] params = Descriptor.getParameterTypes(signature, cp);
  169. CtClass retType = Descriptor.getReturnType(signature, cp);
  170. int paramVar = ca.getMaxLocals();
  171. jc.recordParams(classname, params,
  172. true, paramVar, withinStatic());
  173. int retVar = jc.recordReturnType(retType, true);
  174. if (c == INVOKESTATIC)
  175. jc.recordStaticProceed(classname, methodname);
  176. else if (c == INVOKESPECIAL)
  177. jc.recordSpecialProceed(Javac.param0Name, classname,
  178. methodname, signature);
  179. else
  180. jc.recordProceed(Javac.param0Name, methodname);
  181. /* Is $_ included in the source code?
  182. */
  183. checkResultValue(retType, statement);
  184. Bytecode bytecode = jc.getBytecode();
  185. storeStack(params, c == INVOKESTATIC, paramVar, bytecode);
  186. jc.recordLocalVariables(ca, pos);
  187. jc.compileStmnt(statement);
  188. if (retType != CtClass.voidType)
  189. bytecode.addLoad(retVar, retType);
  190. replace0(pos, bytecode, opcodeSize);
  191. }
  192. catch (CompileError e) { throw new CannotCompileException(e); }
  193. catch (NotFoundException e) { throw new CannotCompileException(e); }
  194. catch (BadBytecode e) {
  195. throw new CannotCompileException("broken method");
  196. }
  197. }
  198. }