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.

NewExpr.java 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2006 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. import javassist.compiler.ast.ASTList;
  20. /**
  21. * Object creation (<tt>new</tt> expression).
  22. */
  23. public class NewExpr extends Expr {
  24. String newTypeName;
  25. int newPos;
  26. /**
  27. * Undocumented constructor. Do not use; internal-use only.
  28. */
  29. protected NewExpr(int pos, CodeIterator i, CtClass declaring,
  30. MethodInfo m, String type, int np) {
  31. super(pos, i, declaring, m);
  32. newTypeName = type;
  33. newPos = np;
  34. }
  35. /*
  36. * Not used
  37. *
  38. private int getNameAndType(ConstPool cp) {
  39. int pos = currentPos;
  40. int c = iterator.byteAt(pos);
  41. int index = iterator.u16bitAt(pos + 1);
  42. if (c == INVOKEINTERFACE)
  43. return cp.getInterfaceMethodrefNameAndType(index);
  44. else
  45. return cp.getMethodrefNameAndType(index);
  46. } */
  47. /**
  48. * Returns the method or constructor containing the <tt>new</tt>
  49. * expression represented by this object.
  50. */
  51. public CtBehavior where() { return super.where(); }
  52. /**
  53. * Returns the line number of the source line containing the
  54. * <tt>new</tt> expression.
  55. *
  56. * @return -1 if this information is not available.
  57. */
  58. public int getLineNumber() {
  59. return super.getLineNumber();
  60. }
  61. /**
  62. * Returns the source file containing the <tt>new</tt> expression.
  63. *
  64. * @return null if this information is not available.
  65. */
  66. public String getFileName() {
  67. return super.getFileName();
  68. }
  69. /**
  70. * Returns the class of the created object.
  71. */
  72. private CtClass getCtClass() throws NotFoundException {
  73. return thisClass.getClassPool().get(newTypeName);
  74. }
  75. /**
  76. * Returns the class name of the created object.
  77. */
  78. public String getClassName() {
  79. return newTypeName;
  80. }
  81. /**
  82. * Get the signature of the constructor
  83. *
  84. * The signature is represented by a character string
  85. * called method descriptor, which is defined in the JVM specification.
  86. *
  87. * @see javassist.CtBehavior#getSignature()
  88. * @see javassist.bytecode.Descriptor
  89. * @return the signature
  90. */
  91. public String getSignature() {
  92. ConstPool constPool = getConstPool();
  93. int methodIndex = iterator.u16bitAt(currentPos + 1); // constructor
  94. return constPool.getMethodrefType(methodIndex);
  95. }
  96. /**
  97. * Returns the constructor called for creating the object.
  98. */
  99. public CtConstructor getConstructor() throws NotFoundException {
  100. ConstPool cp = getConstPool();
  101. int index = iterator.u16bitAt(currentPos + 1);
  102. String desc = cp.getMethodrefType(index);
  103. return getCtClass().getConstructor(desc);
  104. }
  105. /**
  106. * Returns the list of exceptions that the expression may throw.
  107. * This list includes both the exceptions that the try-catch statements
  108. * including the expression can catch and the exceptions that
  109. * the throws declaration allows the method to throw.
  110. */
  111. public CtClass[] mayThrow() {
  112. return super.mayThrow();
  113. }
  114. /*
  115. * Returns the parameter types of the constructor.
  116. public CtClass[] getParameterTypes() throws NotFoundException {
  117. ConstPool cp = getConstPool();
  118. int index = iterator.u16bitAt(currentPos + 1);
  119. String desc = cp.getMethodrefType(index);
  120. return Descriptor.getParameterTypes(desc, thisClass.getClassPool());
  121. }
  122. */
  123. private int canReplace() throws CannotCompileException {
  124. int op = iterator.byteAt(newPos + 3);
  125. if (op == Opcode.DUP)
  126. return 4;
  127. else if (op == Opcode.DUP_X1
  128. && iterator.byteAt(newPos + 4) == Opcode.SWAP)
  129. return 5;
  130. else if (op == Opcode.INVOKESPECIAL)
  131. return 3; // for Eclipse's compiler
  132. else
  133. throw new CannotCompileException(
  134. "sorry, cannot edit NEW followed by no DUP");
  135. }
  136. /**
  137. * Replaces the <tt>new</tt> expression with the bytecode derived from
  138. * the given source text.
  139. *
  140. * <p>$0 is available but the value is null.
  141. *
  142. * @param statement a Java statement.
  143. */
  144. public void replace(String statement) throws CannotCompileException {
  145. final int bytecodeSize = 3;
  146. int pos = newPos;
  147. int newIndex = iterator.u16bitAt(pos + 1);
  148. /* delete the preceding NEW and DUP (or DUP_X1, SWAP) instructions.
  149. */
  150. int end = pos + canReplace();
  151. for (int i = pos; i < end; ++i)
  152. iterator.writeByte(NOP, i);
  153. ConstPool constPool = getConstPool();
  154. pos = currentPos;
  155. int methodIndex = iterator.u16bitAt(pos + 1); // constructor
  156. String signature = constPool.getMethodrefType(methodIndex);
  157. Javac jc = new Javac(thisClass);
  158. ClassPool cp = thisClass.getClassPool();
  159. CodeAttribute ca = iterator.get();
  160. try {
  161. CtClass[] params = Descriptor.getParameterTypes(signature, cp);
  162. CtClass newType = cp.get(newTypeName);
  163. int paramVar = ca.getMaxLocals();
  164. jc.recordParams(newTypeName, params,
  165. true, paramVar, withinStatic());
  166. int retVar = jc.recordReturnType(newType, true);
  167. jc.recordProceed(new ProceedForNew(newType, newIndex,
  168. methodIndex));
  169. /* Is $_ included in the source code?
  170. */
  171. checkResultValue(newType, statement);
  172. Bytecode bytecode = jc.getBytecode();
  173. storeStack(params, true, paramVar, bytecode);
  174. jc.recordLocalVariables(ca, pos);
  175. bytecode.addConstZero(newType);
  176. bytecode.addStore(retVar, newType); // initialize $_
  177. jc.compileStmnt(statement);
  178. bytecode.addAload(retVar);
  179. replace0(pos, bytecode, bytecodeSize);
  180. }
  181. catch (CompileError e) { throw new CannotCompileException(e); }
  182. catch (NotFoundException e) { throw new CannotCompileException(e); }
  183. catch (BadBytecode e) {
  184. throw new CannotCompileException("broken method");
  185. }
  186. }
  187. static class ProceedForNew implements ProceedHandler {
  188. CtClass newType;
  189. int newIndex, methodIndex;
  190. ProceedForNew(CtClass nt, int ni, int mi) {
  191. newType = nt;
  192. newIndex = ni;
  193. methodIndex = mi;
  194. }
  195. public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
  196. throws CompileError
  197. {
  198. bytecode.addOpcode(NEW);
  199. bytecode.addIndex(newIndex);
  200. bytecode.addOpcode(DUP);
  201. gen.atMethodCallCore(newType, MethodInfo.nameInit, args,
  202. false, true, -1, null);
  203. gen.setType(newType);
  204. }
  205. public void setReturnType(JvstTypeChecker c, ASTList args)
  206. throws CompileError
  207. {
  208. c.atMethodCallCore(newType, MethodInfo.nameInit, args);
  209. c.setType(newType);
  210. }
  211. }
  212. }