You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MethodCall.java 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2005 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. protected MethodCall(int pos, CodeIterator i, CtClass declaring,
  27. MethodInfo m) {
  28. super(pos, i, declaring, m);
  29. }
  30. private int getNameAndType(ConstPool cp) {
  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. protected 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. if (cname.charAt(0) == '[')
  83. cname = Descriptor.toClassName(cname);
  84. return cname;
  85. }
  86. /**
  87. * Returns the name of the called method.
  88. */
  89. public String getMethodName() {
  90. ConstPool cp = getConstPool();
  91. int nt = getNameAndType(cp);
  92. return cp.getUtf8Info(cp.getNameAndTypeName(nt));
  93. }
  94. /**
  95. * Returns the called method.
  96. */
  97. public CtMethod getMethod() throws NotFoundException {
  98. return getCtClass().getMethod(getMethodName(), getSignature());
  99. }
  100. /**
  101. * Returns the method signature (the parameter types
  102. * and the return type).
  103. * The method signature is represented by a character string
  104. * called method descriptor, which is defined in the JVM specification.
  105. *
  106. * @see javassist.CtBehavior#getSignature()
  107. * @see javassist.bytecode.Descriptor
  108. * @since 3.1
  109. */
  110. public String getSignature() {
  111. ConstPool cp = getConstPool();
  112. int nt = getNameAndType(cp);
  113. return cp.getUtf8Info(cp.getNameAndTypeDescriptor(nt));
  114. }
  115. /**
  116. * Returns the list of exceptions that the expression may throw.
  117. * This list includes both the exceptions that the try-catch statements
  118. * including the expression can catch and the exceptions that
  119. * the throws declaration allows the method to throw.
  120. */
  121. public CtClass[] mayThrow() {
  122. return super.mayThrow();
  123. }
  124. /**
  125. * Returns true if the called method is of a superclass of the current
  126. * class.
  127. */
  128. public boolean isSuper() {
  129. return iterator.byteAt(currentPos) == INVOKESPECIAL
  130. && !where().getDeclaringClass().getName().equals(getClassName());
  131. }
  132. /*
  133. * Returns the parameter types of the called method.
  134. public CtClass[] getParameterTypes() throws NotFoundException {
  135. return Descriptor.getParameterTypes(getMethodDesc(),
  136. thisClass.getClassPool());
  137. }
  138. */
  139. /*
  140. * Returns the return type of the called method.
  141. public CtClass getReturnType() throws NotFoundException {
  142. return Descriptor.getReturnType(getMethodDesc(),
  143. thisClass.getClassPool());
  144. }
  145. */
  146. /**
  147. * Replaces the method call with the bytecode derived from
  148. * the given source text.
  149. *
  150. * <p>$0 is available even if the called method is static.
  151. *
  152. * @param statement a Java statement.
  153. */
  154. public void replace(String statement) throws CannotCompileException {
  155. ConstPool constPool = getConstPool();
  156. int pos = currentPos;
  157. int index = iterator.u16bitAt(pos + 1);
  158. String classname, methodname, signature;
  159. int opcodeSize;
  160. int c = iterator.byteAt(pos);
  161. if (c == INVOKEINTERFACE) {
  162. opcodeSize = 5;
  163. classname = constPool.getInterfaceMethodrefClassName(index);
  164. methodname = constPool.getInterfaceMethodrefName(index);
  165. signature = constPool.getInterfaceMethodrefType(index);
  166. }
  167. else if (c == INVOKESTATIC
  168. || c == INVOKESPECIAL || c == INVOKEVIRTUAL) {
  169. opcodeSize = 3;
  170. classname = constPool.getMethodrefClassName(index);
  171. methodname = constPool.getMethodrefName(index);
  172. signature = constPool.getMethodrefType(index);
  173. }
  174. else
  175. throw new CannotCompileException("not method invocation");
  176. Javac jc = new Javac(thisClass);
  177. ClassPool cp = thisClass.getClassPool();
  178. CodeAttribute ca = iterator.get();
  179. try {
  180. CtClass[] params = Descriptor.getParameterTypes(signature, cp);
  181. CtClass retType = Descriptor.getReturnType(signature, cp);
  182. int paramVar = ca.getMaxLocals();
  183. jc.recordParams(classname, params,
  184. true, paramVar, withinStatic());
  185. int retVar = jc.recordReturnType(retType, true);
  186. if (c == INVOKESTATIC)
  187. jc.recordStaticProceed(classname, methodname);
  188. else if (c == INVOKESPECIAL)
  189. jc.recordSpecialProceed(Javac.param0Name, classname,
  190. methodname, signature);
  191. else
  192. jc.recordProceed(Javac.param0Name, methodname);
  193. /* Is $_ included in the source code?
  194. */
  195. checkResultValue(retType, statement);
  196. Bytecode bytecode = jc.getBytecode();
  197. storeStack(params, c == INVOKESTATIC, paramVar, bytecode);
  198. jc.recordLocalVariables(ca, pos);
  199. if (retType != CtClass.voidType) {
  200. bytecode.addConstZero(retType);
  201. bytecode.addStore(retVar, retType); // initialize $_
  202. }
  203. jc.compileStmnt(statement);
  204. if (retType != CtClass.voidType)
  205. bytecode.addLoad(retVar, retType);
  206. replace0(pos, bytecode, opcodeSize);
  207. }
  208. catch (CompileError e) { throw new CannotCompileException(e); }
  209. catch (NotFoundException e) { throw new CannotCompileException(e); }
  210. catch (BadBytecode e) {
  211. throw new CannotCompileException("broken method");
  212. }
  213. }
  214. }