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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. * @return the signature
  85. */
  86. public String getSignature()
  87. {
  88. ConstPool constPool = getConstPool();
  89. int methodIndex = iterator.u16bitAt(currentPos + 1); // constructor
  90. return constPool.getMethodrefType(methodIndex);
  91. }
  92. /**
  93. * Returns the constructor called for creating the object.
  94. */
  95. public CtConstructor getConstructor() throws NotFoundException {
  96. ConstPool cp = getConstPool();
  97. int index = iterator.u16bitAt(currentPos + 1);
  98. String desc = cp.getMethodrefType(index);
  99. return getCtClass().getConstructor(desc);
  100. }
  101. /**
  102. * Returns the list of exceptions that the expression may throw.
  103. * This list includes both the exceptions that the try-catch statements
  104. * including the expression can catch and the exceptions that
  105. * the throws declaration allows the method to throw.
  106. */
  107. public CtClass[] mayThrow() {
  108. return super.mayThrow();
  109. }
  110. /*
  111. * Returns the parameter types of the constructor.
  112. public CtClass[] getParameterTypes() throws NotFoundException {
  113. ConstPool cp = getConstPool();
  114. int index = iterator.u16bitAt(currentPos + 1);
  115. String desc = cp.getMethodrefType(index);
  116. return Descriptor.getParameterTypes(desc, thisClass.getClassPool());
  117. }
  118. */
  119. private int canReplace() throws CannotCompileException {
  120. int op = iterator.byteAt(newPos + 3);
  121. if (op == Opcode.DUP)
  122. return 4;
  123. else if (op == Opcode.DUP_X1
  124. && iterator.byteAt(newPos + 4) == Opcode.SWAP)
  125. return 5;
  126. else if (op == Opcode.INVOKESPECIAL)
  127. return 3; // for Eclipse's compiler
  128. else
  129. throw new CannotCompileException(
  130. "sorry, cannot edit NEW followed by no DUP");
  131. }
  132. /**
  133. * Replaces the <tt>new</tt> expression with the bytecode derived from
  134. * the given source text.
  135. *
  136. * <p>$0 is available but the value is null.
  137. *
  138. * @param statement a Java statement.
  139. */
  140. public void replace(String statement) throws CannotCompileException {
  141. final int bytecodeSize = 3;
  142. int pos = newPos;
  143. int newIndex = iterator.u16bitAt(pos + 1);
  144. /* delete the preceding NEW and DUP (or DUP_X1, SWAP) instructions.
  145. */
  146. int end = pos + canReplace();
  147. for (int i = pos; i < end; ++i)
  148. iterator.writeByte(NOP, i);
  149. ConstPool constPool = getConstPool();
  150. pos = currentPos;
  151. int methodIndex = iterator.u16bitAt(pos + 1); // constructor
  152. String signature = constPool.getMethodrefType(methodIndex);
  153. Javac jc = new Javac(thisClass);
  154. ClassPool cp = thisClass.getClassPool();
  155. CodeAttribute ca = iterator.get();
  156. try {
  157. CtClass[] params = Descriptor.getParameterTypes(signature, cp);
  158. CtClass newType = cp.get(newTypeName);
  159. int paramVar = ca.getMaxLocals();
  160. jc.recordParams(newTypeName, params,
  161. true, paramVar, withinStatic());
  162. int retVar = jc.recordReturnType(newType, true);
  163. jc.recordProceed(new ProceedForNew(newType, newIndex,
  164. methodIndex));
  165. /* Is $_ included in the source code?
  166. */
  167. checkResultValue(newType, statement);
  168. Bytecode bytecode = jc.getBytecode();
  169. storeStack(params, true, paramVar, bytecode);
  170. jc.recordLocalVariables(ca, pos);
  171. bytecode.addConstZero(newType);
  172. bytecode.addStore(retVar, newType); // initialize $_
  173. jc.compileStmnt(statement);
  174. bytecode.addAload(retVar);
  175. replace0(pos, bytecode, bytecodeSize);
  176. }
  177. catch (CompileError e) { throw new CannotCompileException(e); }
  178. catch (NotFoundException e) { throw new CannotCompileException(e); }
  179. catch (BadBytecode e) {
  180. throw new CannotCompileException("broken method");
  181. }
  182. }
  183. static class ProceedForNew implements ProceedHandler {
  184. CtClass newType;
  185. int newIndex, methodIndex;
  186. ProceedForNew(CtClass nt, int ni, int mi) {
  187. newType = nt;
  188. newIndex = ni;
  189. methodIndex = mi;
  190. }
  191. public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
  192. throws CompileError
  193. {
  194. bytecode.addOpcode(NEW);
  195. bytecode.addIndex(newIndex);
  196. bytecode.addOpcode(DUP);
  197. gen.atMethodCallCore(newType, MethodInfo.nameInit, args,
  198. false, true, -1, null);
  199. gen.setType(newType);
  200. }
  201. public void setReturnType(JvstTypeChecker c, ASTList args)
  202. throws CompileError
  203. {
  204. c.atMethodCallCore(newType, MethodInfo.nameInit, args);
  205. c.setType(newType);
  206. }
  207. }
  208. }