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.

CtMethod.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999-2003 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;
  16. import javassist.bytecode.*;
  17. import javassist.expr.ExprEditor;
  18. /* Some methods do nothing except calling the super's method.
  19. * They might seem redundant but they are necessary so that javadoc
  20. * includes the description of those methods in the page of this class.
  21. */
  22. /**
  23. * An instance of <code>CtMethod</code> represents a method.
  24. *
  25. * @see CtClass#getDeclaredMethods()
  26. * @see CtNewMethod
  27. */
  28. public final class CtMethod extends CtBehavior {
  29. protected CtMethod next;
  30. protected int cachedHashCode;
  31. CtMethod(MethodInfo minfo, CtClass declaring) {
  32. super(declaring, minfo);
  33. next = null;
  34. cachedHashCode = 0;
  35. }
  36. /**
  37. * Creates a public abstract method. The created method must be
  38. * added to a class with <code>CtClass.addMethod()</code>.
  39. *
  40. * @param declaring the class to which the created method is added.
  41. * @param returnType the type of the returned value
  42. * @param mname the method name
  43. * @param parameters a list of the parameter types
  44. *
  45. * @see CtClass#addMethod(CtMethod)
  46. */
  47. public CtMethod(CtClass returnType, String mname,
  48. CtClass[] parameters, CtClass declaring) {
  49. this(null, declaring);
  50. ConstPool cp = declaring.getClassFile2().getConstPool();
  51. String desc = Descriptor.ofMethod(returnType, parameters);
  52. methodInfo = new MethodInfo(cp, mname, desc);
  53. setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT);
  54. }
  55. /**
  56. * Creates a copy of a <code>CtMethod</code> object.
  57. * The created method must be
  58. * added to a class with <code>CtClass.addMethod()</code>.
  59. *
  60. * <p>All occurrences of class names in the created method
  61. * are replaced with names specified by
  62. * <code>map</code> if <code>map</code> is not <code>null</code>.
  63. *
  64. * <p>For example, suppose that a method <code>at()</code> is as
  65. * follows:
  66. *
  67. * <ul><pre>public X at(int i) {
  68. * return (X)super.elementAt(i);
  69. * }</pre></ul>
  70. *
  71. * <p>(<code>X</code> is a class name.) If <code>map</code> substitutes
  72. * <code>String</code> for <code>X</code>, then the created method is:
  73. *
  74. * <ul><pre>public String at(int i) {
  75. * return (String)super.elementAt(i);
  76. * }</pre></ul>
  77. *
  78. * <p>By default, all the occurrences of the names of the class
  79. * declaring <code>at()</code> and the superclass are replaced
  80. * with the name of the class and the superclass that the
  81. * created method is added to.
  82. * This is done whichever <code>map</code> is null or not.
  83. * To prevent this replacement, call <code>ClassMap.fix()</code>.
  84. *
  85. * <p><b>Note:</b> if the <code>.class</code> notation (for example,
  86. * <code>String.class</code>) is included in an expression, the
  87. * Javac compiler may produce a helper method.
  88. * Since this constructor never
  89. * copies this helper method, the programmers have the responsiblity of
  90. * copying it. Otherwise, use <code>Class.forName()</code> in the
  91. * expression.
  92. *
  93. * @param src the source method.
  94. * @param declaring the class to which the created method is added.
  95. * @param map the hashtable associating original class names
  96. * with substituted names.
  97. * It can be <code>null</code>.
  98. *
  99. * @see CtClass#addMethod(CtMethod)
  100. * @see ClassMap#fix(String)
  101. */
  102. public CtMethod(CtMethod src, CtClass declaring, ClassMap map)
  103. throws CannotCompileException
  104. {
  105. this(null, declaring);
  106. MethodInfo srcInfo = src.methodInfo;
  107. CtClass srcClass = src.getDeclaringClass();
  108. ConstPool cp = declaring.getClassFile2().getConstPool();
  109. if (map == null)
  110. map = new ClassMap();
  111. map.put(srcClass.getName(), declaring.getName());
  112. try {
  113. CtClass srcSuper = srcClass.getSuperclass();
  114. if (srcSuper != null) {
  115. String srcSuperName = srcSuper.getName();
  116. if (!srcSuperName.equals(CtClass.javaLangObject))
  117. map.put(srcSuperName,
  118. declaring.getSuperclass().getName());
  119. }
  120. methodInfo = new MethodInfo(cp, srcInfo.getName(), srcInfo, map);
  121. }
  122. catch (NotFoundException e) {
  123. throw new CannotCompileException(e);
  124. }
  125. catch (BadBytecode e) {
  126. throw new CannotCompileException(e);
  127. }
  128. }
  129. static CtMethod append(CtMethod list, CtMethod tail) {
  130. tail.next = null;
  131. if (list == null)
  132. return tail;
  133. else {
  134. CtMethod lst = list;
  135. while (lst.next != null)
  136. lst = lst.next;
  137. lst.next = tail;
  138. return list;
  139. }
  140. }
  141. static int count(CtMethod m) {
  142. int n = 0;
  143. while (m != null) {
  144. ++n;
  145. m = m.next;
  146. }
  147. return n;
  148. }
  149. /**
  150. * Returns a hash code value for the method.
  151. * If two methods have the same name and signature, then
  152. * the hash codes for the two methods are equal.
  153. */
  154. public int hashCode() {
  155. /* This method is overridden in ExistingMethod for optimization.
  156. */
  157. if (cachedHashCode == 0) {
  158. String signature
  159. = methodInfo.getName() + ':' + methodInfo.getDescriptor();
  160. // System.identityHashCode() returns 0 only for null.
  161. cachedHashCode = System.identityHashCode(signature.intern());
  162. }
  163. return cachedHashCode;
  164. }
  165. /**
  166. * Indicates whether <code>obj</code> has the same name and the
  167. * same signature as this method.
  168. */
  169. public boolean equals(Object obj) {
  170. return obj != null && obj instanceof CtMethod
  171. && obj.hashCode() == hashCode();
  172. }
  173. /**
  174. * Returns the MethodInfo representing the method in the class file.
  175. */
  176. public MethodInfo getMethodInfo() {
  177. return super.getMethodInfo();
  178. }
  179. /**
  180. * Obtains the modifiers of the method.
  181. *
  182. * @return modifiers encoded with
  183. * <code>javassist.Modifier</code>.
  184. * @see Modifier
  185. */
  186. public int getModifiers() {
  187. return super.getModifiers();
  188. }
  189. /**
  190. * Sets the encoded modifiers of the method.
  191. *
  192. * <p>Changing the modifiers may cause a problem.
  193. * For example, if a non-static method is changed to static,
  194. * the method will be rejected by the bytecode verifier.
  195. *
  196. * @see Modifier
  197. */
  198. public void setModifiers(int mod) {
  199. super.setModifiers(mod);
  200. }
  201. /**
  202. * Obtains the name of this method.
  203. */
  204. public String getName() {
  205. return methodInfo.getName();
  206. }
  207. /**
  208. * Changes the name of this method.
  209. */
  210. public void setName(String newname) {
  211. declaringClass.checkModify();
  212. methodInfo.setName(newname);
  213. }
  214. /**
  215. * Returns the class that declares this method.
  216. */
  217. public CtClass getDeclaringClass() {
  218. return super.getDeclaringClass();
  219. }
  220. /**
  221. * Obtains parameter types of this method.
  222. */
  223. public CtClass[] getParameterTypes() throws NotFoundException {
  224. return super.getParameterTypes();
  225. }
  226. /**
  227. * Obtains the type of the returned value.
  228. */
  229. public CtClass getReturnType() throws NotFoundException {
  230. return getReturnType0();
  231. }
  232. /**
  233. * Returns the character string representing the parameter types
  234. * and the return type. If two methods have the same parameter types
  235. * and the return type, <code>getSignature()</code> returns the
  236. * same string.
  237. */
  238. public String getSignature() {
  239. return super.getSignature();
  240. }
  241. /**
  242. * Obtains exceptions that this method may throw.
  243. */
  244. public CtClass[] getExceptionTypes() throws NotFoundException {
  245. return super.getExceptionTypes();
  246. }
  247. /**
  248. * Sets exceptions that this method may throw.
  249. *
  250. * @param types exception types (or null)
  251. */
  252. public void setExceptionTypes(CtClass[] types) throws NotFoundException {
  253. super.setExceptionTypes(types);
  254. }
  255. /**
  256. * Returns true if the method body is empty, that is, <code>{}</code>.
  257. * It also returns true if the method is an abstract method.
  258. */
  259. public boolean isEmpty() {
  260. CodeAttribute ca = getMethodInfo2().getCodeAttribute();
  261. if (ca == null) // abstract or native
  262. return (getModifiers() & Modifier.ABSTRACT) != 0;
  263. CodeIterator it = ca.iterator();
  264. try {
  265. return it.hasNext() && it.byteAt(it.next()) == Opcode.RETURN
  266. && !it.hasNext();
  267. }
  268. catch (BadBytecode e) {}
  269. return false;
  270. }
  271. /**
  272. * Sets a method body.
  273. *
  274. * @param src the source code representing the method body.
  275. * It must be a single statement or block.
  276. * If it is <code>null</code>, the substituted method
  277. * body does nothing except returning zero or null.
  278. */
  279. public void setBody(String src) throws CannotCompileException {
  280. super.setBody(src);
  281. }
  282. /**
  283. * Copies a method body from another method.
  284. * If this method is abstract, the abstract modifier is removed
  285. * after the method body is copied.
  286. *
  287. * <p>All occurrences of the class names in the copied method body
  288. * are replaced with the names specified by
  289. * <code>map</code> if <code>map</code> is not <code>null</code>.
  290. *
  291. * @param src the method that the body is copied from.
  292. * @param map the hashtable associating original class names
  293. * with substituted names.
  294. * It can be <code>null</code>.
  295. */
  296. public void setBody(CtMethod src, ClassMap map)
  297. throws CannotCompileException
  298. {
  299. setBody0(src.declaringClass, src.methodInfo,
  300. declaringClass, methodInfo, map);
  301. }
  302. /**
  303. * Replace a method body with a new method body wrapping the
  304. * given method.
  305. *
  306. * @param mbody the wrapped method
  307. * @param constParam the constant parameter given to
  308. * the wrapped method
  309. * (maybe <code>null</code>).
  310. *
  311. * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
  312. */
  313. public void setWrappedBody(CtMethod mbody, ConstParameter constParam)
  314. throws CannotCompileException
  315. {
  316. declaringClass.checkModify();
  317. CtClass clazz = getDeclaringClass();
  318. CtClass[] params;
  319. CtClass retType;
  320. try {
  321. params = getParameterTypes();
  322. retType = getReturnType();
  323. }
  324. catch (NotFoundException e) {
  325. throw new CannotCompileException(e);
  326. }
  327. Bytecode code = CtNewWrappedMethod.makeBody(clazz,
  328. clazz.getClassFile2(),
  329. mbody,
  330. params, retType,
  331. constParam);
  332. CodeAttribute cattr = code.toCodeAttribute();
  333. methodInfo.setCodeAttribute(cattr);
  334. methodInfo.setAccessFlags(methodInfo.getAccessFlags()
  335. & ~AccessFlag.ABSTRACT);
  336. }
  337. /**
  338. * Obtains an attribute with the given name.
  339. * If that attribute is not found in the class file, this
  340. * method returns null.
  341. *
  342. * @param name attribute name
  343. */
  344. public byte[] getAttribute(String name) {
  345. return super.getAttribute(name);
  346. }
  347. /**
  348. * Adds an attribute. The attribute is saved in the class file.
  349. *
  350. * @param name attribute name
  351. * @param data attribute value
  352. */
  353. public void setAttribute(String name, byte[] data) {
  354. super.setAttribute(name, data);
  355. }
  356. /**
  357. * Declares to use <code>$cflow</code> for this method.
  358. * If <code>$cflow</code> is used, the class files modified
  359. * with Javassist requires a support class
  360. * <code>javassist.runtime.Cflow</code> at runtime
  361. * (other Javassist classes are not required at runtime).
  362. *
  363. * <p>Every <code>$cflow</code> variable is given a unique name.
  364. * For example, if the given name is <code>"Point.paint"</code>,
  365. * then the variable is indicated by <code>$cflow(Point.paint)</code>.
  366. *
  367. * @param name <code>$cflow</code> name. It can include
  368. * alphabets, numbers, <code>_</code>,
  369. * <code>$</code>, and <code>.</code> (dot).
  370. *
  371. * @see javassist.runtime.Cflow
  372. */
  373. public void useCflow(String name) throws CannotCompileException {
  374. super.useCflow(name);
  375. }
  376. /**
  377. * Modifies the method body.
  378. *
  379. * @param converter specifies how to modify.
  380. */
  381. public void instrument(CodeConverter converter)
  382. throws CannotCompileException
  383. {
  384. super.instrument(converter);
  385. }
  386. /**
  387. * Modifies the method body.
  388. *
  389. * @param editor specifies how to modify.
  390. */
  391. public void instrument(ExprEditor editor)
  392. throws CannotCompileException
  393. {
  394. super.instrument(editor);
  395. }
  396. /**
  397. * Inserts bytecode at the beginning of the method body.
  398. *
  399. * @param src the source code representing the inserted bytecode.
  400. * It must be a single statement or block.
  401. */
  402. public void insertBefore(String src) throws CannotCompileException {
  403. super.insertBefore(src);
  404. }
  405. /**
  406. * Inserts bytecode at the end of the method body.
  407. * The bytecode is inserted just before every return insturction.
  408. * It is not executed when an exception is thrown.
  409. *
  410. * @param src the source code representing the inserted bytecode.
  411. * It must be a single statement or block.
  412. */
  413. public void insertAfter(String src)
  414. throws CannotCompileException
  415. {
  416. super.insertAfter(src);
  417. }
  418. /**
  419. * Inserts bytecode at the end of the method body.
  420. * The bytecode is inserted just before every return insturction.
  421. *
  422. * @param src the source code representing the inserted bytecode.
  423. * It must be a single statement or block.
  424. * @param asFinally true if the inserted bytecode is executed
  425. * not only when the transfer normally returns
  426. * but also when an exception is thrown.
  427. */
  428. public void insertAfter(String src, boolean asFinally)
  429. throws CannotCompileException
  430. {
  431. super.insertAfter(src, asFinally);
  432. }
  433. /**
  434. * Adds a catch clause that handles an exception thrown in the
  435. * method body.
  436. * The catch clause must end with a return or throw statement.
  437. *
  438. * @param src the source code representing the catch clause.
  439. * It must be a single statement or block.
  440. * @param exceptionType the type of the exception handled by the
  441. * catch clause.
  442. */
  443. public void addCatch(String src, CtClass exceptionType)
  444. throws CannotCompileException
  445. {
  446. super.addCatch(src, exceptionType);
  447. }
  448. // inner classes
  449. /**
  450. * Instances of this class represent a constant parameter.
  451. * They are used to specify the parameter given to the methods
  452. * created by <code>CtNewMethod.wrapped()</code>.
  453. *
  454. * @see CtMethod#setWrappedBody(CtMethod,CtMethod.ConstParameter)
  455. * @see CtNewMethod#wrapped(CtClass,String,CtClass[],CtClass[],CtMethod,CtMethod.ConstParameter,CtClass)
  456. * @see CtNewConstructor#make(CtClass[],CtClass[],int,CtMethod,CtMethod.ConstParameter,CtClass)
  457. */
  458. public static class ConstParameter {
  459. /**
  460. * Makes an integer constant.
  461. *
  462. * @param i the constant value.
  463. */
  464. public static ConstParameter integer(int i) {
  465. return new IntConstParameter(i);
  466. }
  467. /**
  468. * Makes a long integer constant.
  469. *
  470. * @param i the constant value.
  471. */
  472. public static ConstParameter integer(long i) {
  473. return new LongConstParameter(i);
  474. }
  475. /**
  476. * Makes an <code>String</code> constant.
  477. *
  478. * @param s the constant value.
  479. */
  480. public static ConstParameter string(String s) {
  481. return new StringConstParameter(s);
  482. }
  483. ConstParameter() {}
  484. /**
  485. * @return the size of the stack consumption.
  486. */
  487. int compile(Bytecode code) throws CannotCompileException {
  488. return 0;
  489. }
  490. String descriptor() {
  491. return defaultDescriptor();
  492. }
  493. /**
  494. * @see CtNewWrappedMethod
  495. */
  496. static String defaultDescriptor() {
  497. return "([Ljava/lang/Object;)Ljava/lang/Object;";
  498. }
  499. /**
  500. * Returns the descriptor for constructors.
  501. *
  502. * @see CtNewWrappedConstructor
  503. */
  504. String constDescriptor() {
  505. return defaultConstDescriptor();
  506. }
  507. /**
  508. * Returns the default descriptor for constructors.
  509. */
  510. static String defaultConstDescriptor() {
  511. return "([Ljava/lang/Object;)V";
  512. }
  513. }
  514. static class IntConstParameter extends ConstParameter {
  515. int param;
  516. IntConstParameter(int i) {
  517. param = i;
  518. }
  519. int compile(Bytecode code) throws CannotCompileException {
  520. code.addIconst(param);
  521. return 1;
  522. }
  523. String descriptor() {
  524. return "([Ljava/lang/Object;I)Ljava/lang/Object;";
  525. }
  526. String constDescriptor() {
  527. return "([Ljava/lang/Object;I)V";
  528. }
  529. }
  530. static class LongConstParameter extends ConstParameter {
  531. long param;
  532. LongConstParameter(long l) {
  533. param = l;
  534. }
  535. int compile(Bytecode code) throws CannotCompileException {
  536. code.addLconst(param);
  537. return 2;
  538. }
  539. String descriptor() {
  540. return "([Ljava/lang/Object;J)Ljava/lang/Object;";
  541. }
  542. String constDescriptor() {
  543. return "([Ljava/lang/Object;J)V";
  544. }
  545. }
  546. static class StringConstParameter extends ConstParameter {
  547. String param;
  548. StringConstParameter(String s) {
  549. param = s;
  550. }
  551. int compile(Bytecode code) throws CannotCompileException {
  552. code.addLdc(param);
  553. return 1;
  554. }
  555. String descriptor() {
  556. return "([Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;";
  557. }
  558. String constDescriptor() {
  559. return "([Ljava/lang/Object;Ljava/lang/String;)V";
  560. }
  561. }
  562. }