Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

MethodCall.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2007 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 except try-catch.
  153. */
  154. public void replace(String statement) throws CannotCompileException {
  155. thisClass.getClassFile(); // to call checkModify().
  156. ConstPool constPool = getConstPool();
  157. int pos = currentPos;
  158. int index = iterator.u16bitAt(pos + 1);
  159. String classname, methodname, signature;
  160. int opcodeSize;
  161. int c = iterator.byteAt(pos);
  162. if (c == INVOKEINTERFACE) {
  163. opcodeSize = 5;
  164. classname = constPool.getInterfaceMethodrefClassName(index);
  165. methodname = constPool.getInterfaceMethodrefName(index);
  166. signature = constPool.getInterfaceMethodrefType(index);
  167. }
  168. else if (c == INVOKESTATIC
  169. || c == INVOKESPECIAL || c == INVOKEVIRTUAL) {
  170. opcodeSize = 3;
  171. classname = constPool.getMethodrefClassName(index);
  172. methodname = constPool.getMethodrefName(index);
  173. signature = constPool.getMethodrefType(index);
  174. }
  175. else
  176. throw new CannotCompileException("not method invocation");
  177. Javac jc = new Javac(thisClass);
  178. ClassPool cp = thisClass.getClassPool();
  179. CodeAttribute ca = iterator.get();
  180. try {
  181. CtClass[] params = Descriptor.getParameterTypes(signature, cp);
  182. CtClass retType = Descriptor.getReturnType(signature, cp);
  183. int paramVar = ca.getMaxLocals();
  184. jc.recordParams(classname, params,
  185. true, paramVar, withinStatic());
  186. int retVar = jc.recordReturnType(retType, true);
  187. if (c == INVOKESTATIC)
  188. jc.recordStaticProceed(classname, methodname);
  189. else if (c == INVOKESPECIAL)
  190. jc.recordSpecialProceed(Javac.param0Name, classname,
  191. methodname, signature);
  192. else
  193. jc.recordProceed(Javac.param0Name, methodname);
  194. /* Is $_ included in the source code?
  195. */
  196. checkResultValue(retType, statement);
  197. Bytecode bytecode = jc.getBytecode();
  198. storeStack(params, c == INVOKESTATIC, paramVar, bytecode);
  199. jc.recordLocalVariables(ca, pos);
  200. if (retType != CtClass.voidType) {
  201. bytecode.addConstZero(retType);
  202. bytecode.addStore(retVar, retType); // initialize $_
  203. }
  204. jc.compileStmnt(statement);
  205. if (retType != CtClass.voidType)
  206. bytecode.addLoad(retVar, retType);
  207. replace0(pos, bytecode, opcodeSize);
  208. }
  209. catch (CompileError e) { throw new CannotCompileException(e); }
  210. catch (NotFoundException e) { throw new CannotCompileException(e); }
  211. catch (BadBytecode e) {
  212. throw new CannotCompileException("broken method");
  213. }
  214. }
  215. }