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.2KB

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