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.

Bytecode.java 42KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- 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. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.bytecode;
  17. import javassist.CtClass;
  18. import javassist.CtPrimitiveType;
  19. class ByteVector implements Cloneable {
  20. private byte[] buffer;
  21. private int size;
  22. public ByteVector() {
  23. buffer = new byte[64];
  24. size = 0;
  25. }
  26. public Object clone() throws CloneNotSupportedException {
  27. ByteVector bv = (ByteVector)super.clone();
  28. bv.buffer = (byte[])buffer.clone();
  29. return bv;
  30. }
  31. public final int getSize() { return size; }
  32. public final byte[] copy() {
  33. byte[] b = new byte[size];
  34. System.arraycopy(buffer, 0, b, 0, size);
  35. return b;
  36. }
  37. public int read(int offset) {
  38. if (offset < 0 || size <= offset)
  39. throw new ArrayIndexOutOfBoundsException(offset);
  40. return buffer[offset];
  41. }
  42. public void write(int offset, int value) {
  43. if (offset < 0 || size <= offset)
  44. throw new ArrayIndexOutOfBoundsException(offset);
  45. buffer[offset] = (byte)value;
  46. }
  47. public void add(int code) {
  48. addGap(1);
  49. buffer[size - 1] = (byte)code;
  50. }
  51. public void add(int b1, int b2) {
  52. addGap(2);
  53. buffer[size - 2] = (byte)b1;
  54. buffer[size - 1] = (byte)b2;
  55. }
  56. public void add(int b1, int b2, int b3, int b4) {
  57. addGap(4);
  58. buffer[size - 4] = (byte)b1;
  59. buffer[size - 3] = (byte)b2;
  60. buffer[size - 2] = (byte)b3;
  61. buffer[size - 1] = (byte)b4;
  62. }
  63. public void addGap(int length) {
  64. if (size + length > buffer.length) {
  65. int newSize = size << 1;
  66. if (newSize < size + length)
  67. newSize = size + length;
  68. byte[] newBuf = new byte[newSize];
  69. System.arraycopy(buffer, 0, newBuf, 0, size);
  70. buffer = newBuf;
  71. }
  72. size += length;
  73. }
  74. }
  75. /**
  76. * A utility class for producing a bytecode sequence.
  77. *
  78. * <p>A <code>Bytecode</code> object is an unbounded array
  79. * containing bytecode. For example,
  80. *
  81. * <pre>
  82. * ConstPool cp = ...; // constant pool table
  83. * Bytecode b = new Bytecode(cp, 1, 0);
  84. * b.addIconst(3);
  85. * b.addReturn(CtClass.intType);
  86. * CodeAttribute ca = b.toCodeAttribute();</pre>
  87. *
  88. * <p>This program produces a Code attribute including a bytecode
  89. * sequence:
  90. *
  91. * <pre>
  92. * iconst_3
  93. * ireturn</pre>
  94. *
  95. * @see ConstPool
  96. * @see CodeAttribute
  97. */
  98. public class Bytecode extends ByteVector implements Cloneable, Opcode {
  99. /**
  100. * Represents the <code>CtClass</code> file using the
  101. * constant pool table given to this <code>Bytecode</code> object.
  102. */
  103. public static final CtClass THIS = ConstPool.THIS;
  104. ConstPool constPool;
  105. int maxStack, maxLocals;
  106. ExceptionTable tryblocks;
  107. private int stackDepth;
  108. /**
  109. * Constructs a <code>Bytecode</code> object with an empty bytecode
  110. * sequence.
  111. *
  112. * <p>The parameters <code>stacksize</code> and <code>localvars</code>
  113. * specify initial values
  114. * of <code>max_stack</code> and <code>max_locals</code>.
  115. * They can be changed later.
  116. *
  117. * @param cp constant pool table.
  118. * @param stacksize <code>max_stack</code>.
  119. * @param localvars <code>max_locals</code>.
  120. */
  121. public Bytecode(ConstPool cp, int stacksize, int localvars) {
  122. constPool = cp;
  123. maxStack = stacksize;
  124. maxLocals = localvars;
  125. tryblocks = new ExceptionTable(cp);
  126. stackDepth = 0;
  127. }
  128. /**
  129. * Constructs a <code>Bytecode</code> object with an empty bytecode
  130. * sequence. The initial values of <code>max_stack</code> and
  131. * <code>max_locals</code> are zero.
  132. *
  133. * @param cp constant pool table.
  134. * @see Bytecode#setMaxStack(int)
  135. * @see Bytecode#setMaxLocals(int)
  136. */
  137. public Bytecode(ConstPool cp) {
  138. this(cp, 0, 0);
  139. }
  140. /**
  141. * Creates and returns a copy of this object.
  142. * The constant pool object is shared between this object
  143. * and the cloned object.
  144. */
  145. public Object clone() {
  146. try {
  147. Bytecode bc = (Bytecode)super.clone();
  148. bc.tryblocks = (ExceptionTable)tryblocks.clone();
  149. return bc;
  150. }
  151. catch (CloneNotSupportedException cnse) {
  152. throw new RuntimeException(cnse);
  153. }
  154. }
  155. /**
  156. * Gets a constant pool table.
  157. */
  158. public ConstPool getConstPool() { return constPool; }
  159. /**
  160. * Returns <code>exception_table</code>.
  161. */
  162. public ExceptionTable getExceptionTable() { return tryblocks; }
  163. /**
  164. * Converts to a <code>CodeAttribute</code>.
  165. */
  166. public CodeAttribute toCodeAttribute() {
  167. return new CodeAttribute(constPool, maxStack, maxLocals,
  168. get(), tryblocks);
  169. }
  170. /**
  171. * Returns the length of the bytecode sequence.
  172. */
  173. public int length() {
  174. return getSize();
  175. }
  176. /**
  177. * Returns the produced bytecode sequence.
  178. */
  179. public byte[] get() {
  180. return copy();
  181. }
  182. /**
  183. * Gets <code>max_stack</code>.
  184. */
  185. public int getMaxStack() { return maxStack; }
  186. /**
  187. * Sets <code>max_stack</code>.
  188. *
  189. * <p>This value may be automatically updated when an instruction
  190. * is appended. A <code>Bytecode</code> object maintains the current
  191. * stack depth whenever an instruction is added
  192. * by <code>addOpcode()</code>. For example, if DUP is appended,
  193. * the current stack depth is increased by one. If the new stack
  194. * depth is more than <code>max_stack</code>, then it is assigned
  195. * to <code>max_stack</code>. However, if branch instructions are
  196. * appended, the current stack depth may not be correctly maintained.
  197. *
  198. * @see #addOpcode(int)
  199. */
  200. public void setMaxStack(int size) {
  201. maxStack = size;
  202. }
  203. /**
  204. * Gets <code>max_locals</code>.
  205. */
  206. public int getMaxLocals() { return maxLocals; }
  207. /**
  208. * Sets <code>max_locals</code>.
  209. */
  210. public void setMaxLocals(int size) {
  211. maxLocals = size;
  212. }
  213. /**
  214. * Sets <code>max_locals</code>.
  215. *
  216. * <p>This computes the number of local variables
  217. * used to pass method parameters and sets <code>max_locals</code>
  218. * to that number plus <code>locals</code>.
  219. *
  220. * @param isStatic true if <code>params</code> must be
  221. * interpreted as parameters to a static method.
  222. * @param params parameter types.
  223. * @param locals the number of local variables excluding
  224. * ones used to pass parameters.
  225. */
  226. public void setMaxLocals(boolean isStatic, CtClass[] params,
  227. int locals) {
  228. if (!isStatic)
  229. ++locals;
  230. if (params != null) {
  231. CtClass doubleType = CtClass.doubleType;
  232. CtClass longType = CtClass.longType;
  233. int n = params.length;
  234. for (int i = 0; i < n; ++i) {
  235. CtClass type = params[i];
  236. if (type == doubleType || type == longType)
  237. locals += 2;
  238. else
  239. ++locals;
  240. }
  241. }
  242. maxLocals = locals;
  243. }
  244. /**
  245. * Increments <code>max_locals</code>.
  246. */
  247. public void incMaxLocals(int diff) {
  248. maxLocals += diff;
  249. }
  250. /**
  251. * Adds a new entry of <code>exception_table</code>.
  252. */
  253. public void addExceptionHandler(int start, int end,
  254. int handler, CtClass type) {
  255. addExceptionHandler(start, end, handler,
  256. constPool.addClassInfo(type));
  257. }
  258. /**
  259. * Adds a new entry of <code>exception_table</code>.
  260. *
  261. * @param type the fully-qualified name of a throwable class.
  262. */
  263. public void addExceptionHandler(int start, int end,
  264. int handler, String type) {
  265. addExceptionHandler(start, end, handler,
  266. constPool.addClassInfo(type));
  267. }
  268. /**
  269. * Adds a new entry of <code>exception_table</code>.
  270. */
  271. public void addExceptionHandler(int start, int end,
  272. int handler, int type) {
  273. tryblocks.add(start, end, handler, type);
  274. }
  275. /**
  276. * Returns the length of bytecode sequence
  277. * that have been added so far.
  278. */
  279. public int currentPc() {
  280. return getSize();
  281. }
  282. /**
  283. * Reads a signed 8bit value at the offset from the beginning of the
  284. * bytecode sequence.
  285. *
  286. * @throws ArrayIndexOutOfBoundsException if offset is invalid.
  287. */
  288. public int read(int offset) {
  289. return super.read(offset);
  290. }
  291. /**
  292. * Reads a signed 16bit value at the offset from the beginning of the
  293. * bytecode sequence.
  294. */
  295. public int read16bit(int offset) {
  296. int v1 = read(offset);
  297. int v2 = read(offset + 1);
  298. return (v1 << 8) + (v2 & 0xff);
  299. }
  300. /**
  301. * Reads a signed 32bit value at the offset from the beginning of the
  302. * bytecode sequence.
  303. */
  304. public int read32bit(int offset) {
  305. int v1 = read16bit(offset);
  306. int v2 = read16bit(offset + 2);
  307. return (v1 << 16) + (v2 & 0xffff);
  308. }
  309. /**
  310. * Writes an 8bit value at the offset from the beginning of the
  311. * bytecode sequence.
  312. *
  313. * @throws ArrayIndexOutOfBoundsException if offset is invalid.
  314. */
  315. public void write(int offset, int value) {
  316. super.write(offset, value);
  317. }
  318. /**
  319. * Writes an 16bit value at the offset from the beginning of the
  320. * bytecode sequence.
  321. */
  322. public void write16bit(int offset, int value) {
  323. write(offset, value >> 8);
  324. write(offset + 1, value);
  325. }
  326. /**
  327. * Writes an 32bit value at the offset from the beginning of the
  328. * bytecode sequence.
  329. */
  330. public void write32bit(int offset, int value) {
  331. write16bit(offset, value >> 16);
  332. write16bit(offset + 2, value);
  333. }
  334. /**
  335. * Appends an 8bit value to the end of the bytecode sequence.
  336. */
  337. public void add(int code) {
  338. super.add(code);
  339. }
  340. /**
  341. * Appends a 32bit value to the end of the bytecode sequence.
  342. */
  343. public void add32bit(int value) {
  344. add(value >> 24, value >> 16, value >> 8, value);
  345. }
  346. /**
  347. * Appends the length-byte gap to the end of the bytecode sequence.
  348. *
  349. * @param length the gap length in byte.
  350. */
  351. public void addGap(int length) {
  352. super.addGap(length);
  353. }
  354. /**
  355. * Appends an 8bit opcode to the end of the bytecode sequence.
  356. * The current stack depth is updated.
  357. * <code>max_stack</code> is updated if the current stack depth
  358. * is the deepest so far.
  359. *
  360. * <p>Note: some instructions such as INVOKEVIRTUAL does not
  361. * update the current stack depth since the increment depends
  362. * on the method signature.
  363. * <code>growStack()</code> must be explicitly called.
  364. */
  365. public void addOpcode(int code) {
  366. add(code);
  367. growStack(STACK_GROW[code]);
  368. }
  369. /**
  370. * Increases the current stack depth.
  371. * It also updates <code>max_stack</code> if the current stack depth
  372. * is the deepest so far.
  373. *
  374. * @param diff the number added to the current stack depth.
  375. */
  376. public void growStack(int diff) {
  377. setStackDepth(stackDepth + diff);
  378. }
  379. /**
  380. * Returns the current stack depth.
  381. */
  382. public int getStackDepth() { return stackDepth; }
  383. /**
  384. * Sets the current stack depth.
  385. * It also updates <code>max_stack</code> if the current stack depth
  386. * is the deepest so far.
  387. *
  388. * @param depth new value.
  389. */
  390. public void setStackDepth(int depth) {
  391. stackDepth = depth;
  392. if (stackDepth > maxStack)
  393. maxStack = stackDepth;
  394. }
  395. /**
  396. * Appends a 16bit value to the end of the bytecode sequence.
  397. * It never changes the current stack depth.
  398. */
  399. public void addIndex(int index) {
  400. add(index >> 8, index);
  401. }
  402. /**
  403. * Appends ALOAD or (WIDE) ALOAD_&lt;n&gt;
  404. *
  405. * @param n an index into the local variable array.
  406. */
  407. public void addAload(int n) {
  408. if (n < 4)
  409. addOpcode(42 + n); // aload_<n>
  410. else if (n < 0x100) {
  411. addOpcode(ALOAD); // aload
  412. add(n);
  413. }
  414. else {
  415. addOpcode(WIDE);
  416. addOpcode(ALOAD);
  417. addIndex(n);
  418. }
  419. }
  420. /**
  421. * Appends ASTORE or (WIDE) ASTORE_&lt;n&gt;
  422. *
  423. * @param n an index into the local variable array.
  424. */
  425. public void addAstore(int n) {
  426. if (n < 4)
  427. addOpcode(75 + n); // astore_<n>
  428. else if (n < 0x100) {
  429. addOpcode(ASTORE); // astore
  430. add(n);
  431. }
  432. else {
  433. addOpcode(WIDE);
  434. addOpcode(ASTORE);
  435. addIndex(n);
  436. }
  437. }
  438. /**
  439. * Appends ICONST or ICONST_&lt;n&gt;
  440. *
  441. * @param n the pushed integer constant.
  442. */
  443. public void addIconst(int n) {
  444. if (n < 6 && -2 < n)
  445. addOpcode(3 + n); // iconst_<i> -1..5
  446. else if (n <= 127 && -128 <= n) {
  447. addOpcode(16); // bipush
  448. add(n);
  449. }
  450. else if (n <= 32767 && -32768 <= n) {
  451. addOpcode(17); // sipush
  452. add(n >> 8);
  453. add(n);
  454. }
  455. else
  456. addLdc(constPool.addIntegerInfo(n));
  457. }
  458. /**
  459. * Appends an instruction for pushing zero or null on the stack.
  460. * If the type is void, this method does not append any instruction.
  461. *
  462. * @param type the type of the zero value (or null).
  463. */
  464. public void addConstZero(CtClass type) {
  465. if (type.isPrimitive()) {
  466. if (type == CtClass.longType)
  467. addOpcode(LCONST_0);
  468. else if (type == CtClass.floatType)
  469. addOpcode(FCONST_0);
  470. else if (type == CtClass.doubleType)
  471. addOpcode(DCONST_0);
  472. else if (type == CtClass.voidType)
  473. throw new RuntimeException("void type?");
  474. else
  475. addOpcode(ICONST_0);
  476. }
  477. else
  478. addOpcode(ACONST_NULL);
  479. }
  480. /**
  481. * Appends ILOAD or (WIDE) ILOAD_&lt;n&gt;
  482. *
  483. * @param n an index into the local variable array.
  484. */
  485. public void addIload(int n) {
  486. if (n < 4)
  487. addOpcode(26 + n); // iload_<n>
  488. else if (n < 0x100) {
  489. addOpcode(ILOAD); // iload
  490. add(n);
  491. }
  492. else {
  493. addOpcode(WIDE);
  494. addOpcode(ILOAD);
  495. addIndex(n);
  496. }
  497. }
  498. /**
  499. * Appends ISTORE or (WIDE) ISTORE_&lt;n&gt;
  500. *
  501. * @param n an index into the local variable array.
  502. */
  503. public void addIstore(int n) {
  504. if (n < 4)
  505. addOpcode(59 + n); // istore_<n>
  506. else if (n < 0x100) {
  507. addOpcode(ISTORE); // istore
  508. add(n);
  509. }
  510. else {
  511. addOpcode(WIDE);
  512. addOpcode(ISTORE);
  513. addIndex(n);
  514. }
  515. }
  516. /**
  517. * Appends LCONST or LCONST_&lt;n&gt;
  518. *
  519. * @param n the pushed long integer constant.
  520. */
  521. public void addLconst(long n) {
  522. if (n == 0 || n == 1)
  523. addOpcode(9 + (int)n); // lconst_<n>
  524. else
  525. addLdc2w(n);
  526. }
  527. /**
  528. * Appends LLOAD or (WIDE) LLOAD_&lt;n&gt;
  529. *
  530. * @param n an index into the local variable array.
  531. */
  532. public void addLload(int n) {
  533. if (n < 4)
  534. addOpcode(30 + n); // lload_<n>
  535. else if (n < 0x100) {
  536. addOpcode(LLOAD); // lload
  537. add(n);
  538. }
  539. else {
  540. addOpcode(WIDE);
  541. addOpcode(LLOAD);
  542. addIndex(n);
  543. }
  544. }
  545. /**
  546. * Appends LSTORE or LSTORE_&lt;n&gt;
  547. *
  548. * @param n an index into the local variable array.
  549. */
  550. public void addLstore(int n) {
  551. if (n < 4)
  552. addOpcode(63 + n); // lstore_<n>
  553. else if (n < 0x100) {
  554. addOpcode(LSTORE); // lstore
  555. add(n);
  556. }
  557. else {
  558. addOpcode(WIDE);
  559. addOpcode(LSTORE);
  560. addIndex(n);
  561. }
  562. }
  563. /**
  564. * Appends DCONST or DCONST_&lt;n&gt;
  565. *
  566. * @param d the pushed double constant.
  567. */
  568. public void addDconst(double d) {
  569. if (d == 0.0 || d == 1.0)
  570. addOpcode(14 + (int)d); // dconst_<n>
  571. else
  572. addLdc2w(d);
  573. }
  574. /**
  575. * Appends DLOAD or (WIDE) DLOAD_&lt;n&gt;
  576. *
  577. * @param n an index into the local variable array.
  578. */
  579. public void addDload(int n) {
  580. if (n < 4)
  581. addOpcode(38 + n); // dload_<n>
  582. else if (n < 0x100) {
  583. addOpcode(DLOAD); // dload
  584. add(n);
  585. }
  586. else {
  587. addOpcode(WIDE);
  588. addOpcode(DLOAD);
  589. addIndex(n);
  590. }
  591. }
  592. /**
  593. * Appends DSTORE or (WIDE) DSTORE_&lt;n&gt;
  594. *
  595. * @param n an index into the local variable array.
  596. */
  597. public void addDstore(int n) {
  598. if (n < 4)
  599. addOpcode(71 + n); // dstore_<n>
  600. else if (n < 0x100) {
  601. addOpcode(DSTORE); // dstore
  602. add(n);
  603. }
  604. else {
  605. addOpcode(WIDE);
  606. addOpcode(DSTORE);
  607. addIndex(n);
  608. }
  609. }
  610. /**
  611. * Appends FCONST or FCONST_&lt;n&gt;
  612. *
  613. * @param f the pushed float constant.
  614. */
  615. public void addFconst(float f) {
  616. if (f == 0.0f || f == 1.0f || f == 2.0f)
  617. addOpcode(11 + (int)f); // fconst_<n>
  618. else
  619. addLdc(constPool.addFloatInfo(f));
  620. }
  621. /**
  622. * Appends FLOAD or (WIDE) FLOAD_&lt;n&gt;
  623. *
  624. * @param n an index into the local variable array.
  625. */
  626. public void addFload(int n) {
  627. if (n < 4)
  628. addOpcode(34 + n); // fload_<n>
  629. else if (n < 0x100) {
  630. addOpcode(FLOAD); // fload
  631. add(n);
  632. }
  633. else {
  634. addOpcode(WIDE);
  635. addOpcode(FLOAD);
  636. addIndex(n);
  637. }
  638. }
  639. /**
  640. * Appends FSTORE or FSTORE_&lt;n&gt;
  641. *
  642. * @param n an index into the local variable array.
  643. */
  644. public void addFstore(int n) {
  645. if (n < 4)
  646. addOpcode(67 + n); // fstore_<n>
  647. else if (n < 0x100) {
  648. addOpcode(FSTORE); // fstore
  649. add(n);
  650. }
  651. else {
  652. addOpcode(WIDE);
  653. addOpcode(FSTORE);
  654. addIndex(n);
  655. }
  656. }
  657. /**
  658. * Appends an instruction for loading a value from the
  659. * local variable at the index <code>n</code>.
  660. *
  661. * @param n the index.
  662. * @param type the type of the loaded value.
  663. * @return the size of the value (1 or 2 word).
  664. */
  665. public int addLoad(int n, CtClass type) {
  666. if (type.isPrimitive()) {
  667. if (type == CtClass.booleanType || type == CtClass.charType
  668. || type == CtClass.byteType || type == CtClass.shortType
  669. || type == CtClass.intType)
  670. addIload(n);
  671. else if (type == CtClass.longType) {
  672. addLload(n);
  673. return 2;
  674. }
  675. else if(type == CtClass.floatType)
  676. addFload(n);
  677. else if(type == CtClass.doubleType) {
  678. addDload(n);
  679. return 2;
  680. }
  681. else
  682. throw new RuntimeException("void type?");
  683. }
  684. else
  685. addAload(n);
  686. return 1;
  687. }
  688. /**
  689. * Appends an instruction for storing a value into the
  690. * local variable at the index <code>n</code>.
  691. *
  692. * @param n the index.
  693. * @param type the type of the stored value.
  694. * @return 2 if the type is long or double. Otherwise 1.
  695. */
  696. public int addStore(int n, CtClass type) {
  697. if (type.isPrimitive()) {
  698. if (type == CtClass.booleanType || type == CtClass.charType
  699. || type == CtClass.byteType || type == CtClass.shortType
  700. || type == CtClass.intType)
  701. addIstore(n);
  702. else if (type == CtClass.longType) {
  703. addLstore(n);
  704. return 2;
  705. }
  706. else if (type == CtClass.floatType)
  707. addFstore(n);
  708. else if (type == CtClass.doubleType) {
  709. addDstore(n);
  710. return 2;
  711. }
  712. else
  713. throw new RuntimeException("void type?");
  714. }
  715. else
  716. addAstore(n);
  717. return 1;
  718. }
  719. /**
  720. * Appends instructions for loading all the parameters onto the
  721. * operand stack.
  722. *
  723. * @param offset the index of the first parameter. It is 0
  724. * if the method is static. Otherwise, it is 1.
  725. */
  726. public int addLoadParameters(CtClass[] params, int offset) {
  727. int stacksize = 0;
  728. if (params != null) {
  729. int n = params.length;
  730. for (int i = 0; i < n; ++i)
  731. stacksize += addLoad(stacksize + offset, params[i]);
  732. }
  733. return stacksize;
  734. }
  735. /**
  736. * Appends CHECKCAST.
  737. *
  738. * @param c the type.
  739. */
  740. public void addCheckcast(CtClass c) {
  741. addOpcode(CHECKCAST);
  742. addIndex(constPool.addClassInfo(c));
  743. }
  744. /**
  745. * Appends CHECKCAST.
  746. *
  747. * @param classname a fully-qualified class name.
  748. */
  749. public void addCheckcast(String classname) {
  750. addOpcode(CHECKCAST);
  751. addIndex(constPool.addClassInfo(classname));
  752. }
  753. /**
  754. * Appends INSTANCEOF.
  755. *
  756. * @param classname the class name.
  757. */
  758. public void addInstanceof(String classname) {
  759. addOpcode(INSTANCEOF);
  760. addIndex(constPool.addClassInfo(classname));
  761. }
  762. /**
  763. * Appends GETFIELD.
  764. *
  765. * @param c the class.
  766. * @param name the field name.
  767. * @param type the descriptor of the field type.
  768. *
  769. * @see Descriptor#of(CtClass)
  770. */
  771. public void addGetfield(CtClass c, String name, String type) {
  772. add(GETFIELD);
  773. int ci = constPool.addClassInfo(c);
  774. addIndex(constPool.addFieldrefInfo(ci, name, type));
  775. growStack(Descriptor.dataSize(type) - 1);
  776. }
  777. /**
  778. * Appends GETFIELD.
  779. *
  780. * @param c the fully-qualified class name.
  781. * @param name the field name.
  782. * @param type the descriptor of the field type.
  783. *
  784. * @see Descriptor#of(CtClass)
  785. */
  786. public void addGetfield(String c, String name, String type) {
  787. add(GETFIELD);
  788. int ci = constPool.addClassInfo(c);
  789. addIndex(constPool.addFieldrefInfo(ci, name, type));
  790. growStack(Descriptor.dataSize(type) - 1);
  791. }
  792. /**
  793. * Appends GETSTATIC.
  794. *
  795. * @param c the class
  796. * @param name the field name
  797. * @param type the descriptor of the field type.
  798. *
  799. * @see Descriptor#of(CtClass)
  800. */
  801. public void addGetstatic(CtClass c, String name, String type) {
  802. add(GETSTATIC);
  803. int ci = constPool.addClassInfo(c);
  804. addIndex(constPool.addFieldrefInfo(ci, name, type));
  805. growStack(Descriptor.dataSize(type));
  806. }
  807. /**
  808. * Appends GETSTATIC.
  809. *
  810. * @param c the fully-qualified class name
  811. * @param name the field name
  812. * @param type the descriptor of the field type.
  813. *
  814. * @see Descriptor#of(CtClass)
  815. */
  816. public void addGetstatic(String c, String name, String type) {
  817. add(GETSTATIC);
  818. int ci = constPool.addClassInfo(c);
  819. addIndex(constPool.addFieldrefInfo(ci, name, type));
  820. growStack(Descriptor.dataSize(type));
  821. }
  822. /**
  823. * Appends INVOKESPECIAL.
  824. *
  825. * @param clazz the target class.
  826. * @param name the method name.
  827. * @param returnType the return type.
  828. * @param paramTypes the parameter types.
  829. */
  830. public void addInvokespecial(CtClass clazz, String name,
  831. CtClass returnType, CtClass[] paramTypes) {
  832. String desc = Descriptor.ofMethod(returnType, paramTypes);
  833. addInvokespecial(clazz, name, desc);
  834. }
  835. /**
  836. * Appends INVOKESPECIAL.
  837. *
  838. * @param clazz the target class.
  839. * @param name the method name
  840. * @param desc the descriptor of the method signature.
  841. *
  842. * @see Descriptor#ofMethod(CtClass,CtClass[])
  843. * @see Descriptor#ofConstructor(CtClass[])
  844. */
  845. public void addInvokespecial(CtClass clazz, String name, String desc) {
  846. boolean isInterface = clazz == null ? false : clazz.isInterface();
  847. addInvokespecial(isInterface,
  848. constPool.addClassInfo(clazz), name, desc);
  849. }
  850. /**
  851. * Appends INVOKESPECIAL. The invoked method must not be a default
  852. * method declared in an interface.
  853. *
  854. * @param clazz the fully-qualified class name.
  855. * @param name the method name
  856. * @param desc the descriptor of the method signature.
  857. *
  858. * @see Descriptor#ofMethod(CtClass,CtClass[])
  859. * @see Descriptor#ofConstructor(CtClass[])
  860. */
  861. public void addInvokespecial(String clazz, String name, String desc) {
  862. addInvokespecial(false, constPool.addClassInfo(clazz), name, desc);
  863. }
  864. /**
  865. * Appends INVOKESPECIAL. The invoked method must not be a default
  866. * method declared in an interface.
  867. *
  868. * @param clazz the index of <code>CONSTANT_Class_info</code>
  869. * structure.
  870. * @param name the method name
  871. * @param desc the descriptor of the method signature.
  872. *
  873. * @see Descriptor#ofMethod(CtClass,CtClass[])
  874. * @see Descriptor#ofConstructor(CtClass[])
  875. */
  876. public void addInvokespecial(int clazz, String name, String desc) {
  877. addInvokespecial(false, clazz, name, desc);
  878. }
  879. /**
  880. * Appends INVOKESPECIAL.
  881. *
  882. * @param isInterface true if the invoked method is a default method
  883. * declared in an interface.
  884. * @param clazz the index of <code>CONSTANT_Class_info</code>
  885. * structure.
  886. * @param name the method name
  887. * @param desc the descriptor of the method signature.
  888. *
  889. * @see Descriptor#ofMethod(CtClass,CtClass[])
  890. * @see Descriptor#ofConstructor(CtClass[])
  891. */
  892. public void addInvokespecial(boolean isInterface, int clazz, String name, String desc) {
  893. add(INVOKESPECIAL);
  894. int index;
  895. if (isInterface)
  896. index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
  897. else
  898. index = constPool.addMethodrefInfo(clazz, name, desc);
  899. addIndex(index);
  900. growStack(Descriptor.dataSize(desc) - 1);
  901. }
  902. /**
  903. * Appends INVOKESTATIC.
  904. *
  905. * @param clazz the target class.
  906. * @param name the method name
  907. * @param returnType the return type.
  908. * @param paramTypes the parameter types.
  909. */
  910. public void addInvokestatic(CtClass clazz, String name,
  911. CtClass returnType, CtClass[] paramTypes) {
  912. String desc = Descriptor.ofMethod(returnType, paramTypes);
  913. addInvokestatic(clazz, name, desc);
  914. }
  915. /**
  916. * Appends INVOKESTATIC.
  917. *
  918. * @param clazz the target class.
  919. * @param name the method name
  920. * @param desc the descriptor of the method signature.
  921. *
  922. * @see Descriptor#ofMethod(CtClass,CtClass[])
  923. */
  924. public void addInvokestatic(CtClass clazz, String name, String desc) {
  925. addInvokestatic(constPool.addClassInfo(clazz), name, desc);
  926. }
  927. /**
  928. * Appends INVOKESTATIC.
  929. *
  930. * @param classname the fully-qualified class name.
  931. * @param name the method name
  932. * @param desc the descriptor of the method signature.
  933. *
  934. * @see Descriptor#ofMethod(CtClass,CtClass[])
  935. */
  936. public void addInvokestatic(String classname, String name, String desc) {
  937. addInvokestatic(constPool.addClassInfo(classname), name, desc);
  938. }
  939. /**
  940. * Appends INVOKESTATIC.
  941. *
  942. * @param clazz the index of <code>CONSTANT_Class_info</code>
  943. * structure.
  944. * @param name the method name
  945. * @param desc the descriptor of the method signature.
  946. *
  947. * @see Descriptor#ofMethod(CtClass,CtClass[])
  948. */
  949. public void addInvokestatic(int clazz, String name, String desc) {
  950. add(INVOKESTATIC);
  951. addIndex(constPool.addMethodrefInfo(clazz, name, desc));
  952. growStack(Descriptor.dataSize(desc));
  953. }
  954. /**
  955. * Appends INVOKEVIRTUAL.
  956. *
  957. * <p>The specified method must not be an inherited method.
  958. * It must be directly declared in the class specified
  959. * in <code>clazz</code>.
  960. *
  961. * @param clazz the target class.
  962. * @param name the method name
  963. * @param returnType the return type.
  964. * @param paramTypes the parameter types.
  965. */
  966. public void addInvokevirtual(CtClass clazz, String name,
  967. CtClass returnType, CtClass[] paramTypes) {
  968. String desc = Descriptor.ofMethod(returnType, paramTypes);
  969. addInvokevirtual(clazz, name, desc);
  970. }
  971. /**
  972. * Appends INVOKEVIRTUAL.
  973. *
  974. * <p>The specified method must not be an inherited method.
  975. * It must be directly declared in the class specified
  976. * in <code>clazz</code>.
  977. *
  978. * @param clazz the target class.
  979. * @param name the method name
  980. * @param desc the descriptor of the method signature.
  981. *
  982. * @see Descriptor#ofMethod(CtClass,CtClass[])
  983. */
  984. public void addInvokevirtual(CtClass clazz, String name, String desc) {
  985. addInvokevirtual(constPool.addClassInfo(clazz), name, desc);
  986. }
  987. /**
  988. * Appends INVOKEVIRTUAL.
  989. *
  990. * <p>The specified method must not be an inherited method.
  991. * It must be directly declared in the class specified
  992. * in <code>classname</code>.
  993. *
  994. * @param classname the fully-qualified class name.
  995. * @param name the method name
  996. * @param desc the descriptor of the method signature.
  997. *
  998. * @see Descriptor#ofMethod(CtClass,CtClass[])
  999. */
  1000. public void addInvokevirtual(String classname, String name, String desc) {
  1001. addInvokevirtual(constPool.addClassInfo(classname), name, desc);
  1002. }
  1003. /**
  1004. * Appends INVOKEVIRTUAL.
  1005. *
  1006. * <p>The specified method must not be an inherited method.
  1007. * It must be directly declared in the class specified
  1008. * by <code>clazz</code>.
  1009. *
  1010. * @param clazz the index of <code>CONSTANT_Class_info</code>
  1011. * structure.
  1012. * @param name the method name
  1013. * @param desc the descriptor of the method signature.
  1014. *
  1015. * @see Descriptor#ofMethod(CtClass,CtClass[])
  1016. */
  1017. public void addInvokevirtual(int clazz, String name, String desc) {
  1018. add(INVOKEVIRTUAL);
  1019. addIndex(constPool.addMethodrefInfo(clazz, name, desc));
  1020. growStack(Descriptor.dataSize(desc) - 1);
  1021. }
  1022. /**
  1023. * Appends INVOKEINTERFACE.
  1024. *
  1025. * @param clazz the target class.
  1026. * @param name the method name
  1027. * @param returnType the return type.
  1028. * @param paramTypes the parameter types.
  1029. * @param count the count operand of the instruction.
  1030. */
  1031. public void addInvokeinterface(CtClass clazz, String name,
  1032. CtClass returnType, CtClass[] paramTypes,
  1033. int count) {
  1034. String desc = Descriptor.ofMethod(returnType, paramTypes);
  1035. addInvokeinterface(clazz, name, desc, count);
  1036. }
  1037. /**
  1038. * Appends INVOKEINTERFACE.
  1039. *
  1040. * @param clazz the target class.
  1041. * @param name the method name
  1042. * @param desc the descriptor of the method signature.
  1043. * @param count the count operand of the instruction.
  1044. *
  1045. * @see Descriptor#ofMethod(CtClass,CtClass[])
  1046. */
  1047. public void addInvokeinterface(CtClass clazz, String name,
  1048. String desc, int count) {
  1049. addInvokeinterface(constPool.addClassInfo(clazz), name, desc,
  1050. count);
  1051. }
  1052. /**
  1053. * Appends INVOKEINTERFACE.
  1054. *
  1055. * @param classname the fully-qualified class name.
  1056. * @param name the method name
  1057. * @param desc the descriptor of the method signature.
  1058. * @param count the count operand of the instruction.
  1059. *
  1060. * @see Descriptor#ofMethod(CtClass,CtClass[])
  1061. */
  1062. public void addInvokeinterface(String classname, String name,
  1063. String desc, int count) {
  1064. addInvokeinterface(constPool.addClassInfo(classname), name, desc,
  1065. count);
  1066. }
  1067. /**
  1068. * Appends INVOKEINTERFACE.
  1069. *
  1070. * @param clazz the index of <code>CONSTANT_Class_info</code>
  1071. * structure.
  1072. * @param name the method name
  1073. * @param desc the descriptor of the method signature.
  1074. * @param count the count operand of the instruction.
  1075. *
  1076. * @see Descriptor#ofMethod(CtClass,CtClass[])
  1077. */
  1078. public void addInvokeinterface(int clazz, String name,
  1079. String desc, int count) {
  1080. add(INVOKEINTERFACE);
  1081. addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc));
  1082. add(count);
  1083. add(0);
  1084. growStack(Descriptor.dataSize(desc) - 1);
  1085. }
  1086. /**
  1087. * Appends INVOKEDYNAMIC.
  1088. *
  1089. * @param bootstrap an index into the <code>bootstrap_methods</code> array
  1090. * of the bootstrap method table.
  1091. * @param name the method name.
  1092. * @param desc the method descriptor.
  1093. * @see Descriptor#ofMethod(CtClass,CtClass[])
  1094. * @since 3.17
  1095. */
  1096. public void addInvokedynamic(int bootstrap, String name, String desc) {
  1097. int nt = constPool.addNameAndTypeInfo(name, desc);
  1098. int dyn = constPool.addInvokeDynamicInfo(bootstrap, nt);
  1099. add(INVOKEDYNAMIC);
  1100. addIndex(dyn);
  1101. add(0, 0);
  1102. growStack(Descriptor.dataSize(desc)); // assume ConstPool#REF_invokeStatic
  1103. }
  1104. /**
  1105. * Appends LDC or LDC_W. The pushed item is a <code>String</code>
  1106. * object.
  1107. *
  1108. * @param s the character string pushed by LDC or LDC_W.
  1109. */
  1110. public void addLdc(String s) {
  1111. addLdc(constPool.addStringInfo(s));
  1112. }
  1113. /**
  1114. * Appends LDC or LDC_W.
  1115. *
  1116. * @param i index into the constant pool.
  1117. */
  1118. public void addLdc(int i) {
  1119. if (i > 0xFF) {
  1120. addOpcode(LDC_W);
  1121. addIndex(i);
  1122. }
  1123. else {
  1124. addOpcode(LDC);
  1125. add(i);
  1126. }
  1127. }
  1128. /**
  1129. * Appends LDC2_W. The pushed item is a long value.
  1130. */
  1131. public void addLdc2w(long l) {
  1132. addOpcode(LDC2_W);
  1133. addIndex(constPool.addLongInfo(l));
  1134. }
  1135. /**
  1136. * Appends LDC2_W. The pushed item is a double value.
  1137. */
  1138. public void addLdc2w(double d) {
  1139. addOpcode(LDC2_W);
  1140. addIndex(constPool.addDoubleInfo(d));
  1141. }
  1142. /**
  1143. * Appends NEW.
  1144. *
  1145. * @param clazz the class of the created instance.
  1146. */
  1147. public void addNew(CtClass clazz) {
  1148. addOpcode(NEW);
  1149. addIndex(constPool.addClassInfo(clazz));
  1150. }
  1151. /**
  1152. * Appends NEW.
  1153. *
  1154. * @param classname the fully-qualified class name.
  1155. */
  1156. public void addNew(String classname) {
  1157. addOpcode(NEW);
  1158. addIndex(constPool.addClassInfo(classname));
  1159. }
  1160. /**
  1161. * Appends ANEWARRAY.
  1162. *
  1163. * @param classname the qualified class name of the element type.
  1164. */
  1165. public void addAnewarray(String classname) {
  1166. addOpcode(ANEWARRAY);
  1167. addIndex(constPool.addClassInfo(classname));
  1168. }
  1169. /**
  1170. * Appends ICONST and ANEWARRAY.
  1171. *
  1172. * @param clazz the elememnt type.
  1173. * @param length the array length.
  1174. */
  1175. public void addAnewarray(CtClass clazz, int length) {
  1176. addIconst(length);
  1177. addOpcode(ANEWARRAY);
  1178. addIndex(constPool.addClassInfo(clazz));
  1179. }
  1180. /**
  1181. * Appends NEWARRAY for primitive types.
  1182. *
  1183. * @param atype <code>T_BOOLEAN</code>, <code>T_CHAR</code>, ...
  1184. * @see Opcode
  1185. */
  1186. public void addNewarray(int atype, int length) {
  1187. addIconst(length);
  1188. addOpcode(NEWARRAY);
  1189. add(atype);
  1190. }
  1191. /**
  1192. * Appends MULTINEWARRAY.
  1193. *
  1194. * @param clazz the array type.
  1195. * @param dimensions the sizes of all dimensions.
  1196. * @return the length of <code>dimensions</code>.
  1197. */
  1198. public int addMultiNewarray(CtClass clazz, int[] dimensions) {
  1199. int len = dimensions.length;
  1200. for (int i = 0; i < len; ++i)
  1201. addIconst(dimensions[i]);
  1202. growStack(len);
  1203. return addMultiNewarray(clazz, len);
  1204. }
  1205. /**
  1206. * Appends MULTINEWARRAY. The size of every dimension must have been
  1207. * already pushed on the stack.
  1208. *
  1209. * @param clazz the array type.
  1210. * @param dim the number of the dimensions.
  1211. * @return the value of <code>dim</code>.
  1212. */
  1213. public int addMultiNewarray(CtClass clazz, int dim) {
  1214. add(MULTIANEWARRAY);
  1215. addIndex(constPool.addClassInfo(clazz));
  1216. add(dim);
  1217. growStack(1 - dim);
  1218. return dim;
  1219. }
  1220. /**
  1221. * Appends MULTINEWARRAY.
  1222. *
  1223. * @param desc the type descriptor of the created array.
  1224. * @param dim dimensions.
  1225. * @return the value of <code>dim</code>.
  1226. */
  1227. public int addMultiNewarray(String desc, int dim) {
  1228. add(MULTIANEWARRAY);
  1229. addIndex(constPool.addClassInfo(desc));
  1230. add(dim);
  1231. growStack(1 - dim);
  1232. return dim;
  1233. }
  1234. /**
  1235. * Appends PUTFIELD.
  1236. *
  1237. * @param c the target class.
  1238. * @param name the field name.
  1239. * @param desc the descriptor of the field type.
  1240. */
  1241. public void addPutfield(CtClass c, String name, String desc) {
  1242. addPutfield0(c, null, name, desc);
  1243. }
  1244. /**
  1245. * Appends PUTFIELD.
  1246. *
  1247. * @param classname the fully-qualified name of the target class.
  1248. * @param name the field name.
  1249. * @param desc the descriptor of the field type.
  1250. */
  1251. public void addPutfield(String classname, String name, String desc) {
  1252. // if classnaem is null, the target class is THIS.
  1253. addPutfield0(null, classname, name, desc);
  1254. }
  1255. private void addPutfield0(CtClass target, String classname,
  1256. String name, String desc) {
  1257. add(PUTFIELD);
  1258. // target is null if it represents THIS.
  1259. int ci = classname == null ? constPool.addClassInfo(target)
  1260. : constPool.addClassInfo(classname);
  1261. addIndex(constPool.addFieldrefInfo(ci, name, desc));
  1262. growStack(-1 - Descriptor.dataSize(desc));
  1263. }
  1264. /**
  1265. * Appends PUTSTATIC.
  1266. *
  1267. * @param c the target class.
  1268. * @param name the field name.
  1269. * @param desc the descriptor of the field type.
  1270. */
  1271. public void addPutstatic(CtClass c, String name, String desc) {
  1272. addPutstatic0(c, null, name, desc);
  1273. }
  1274. /**
  1275. * Appends PUTSTATIC.
  1276. *
  1277. * @param classname the fully-qualified name of the target class.
  1278. * @param fieldName the field name.
  1279. * @param desc the descriptor of the field type.
  1280. */
  1281. public void addPutstatic(String classname, String fieldName, String desc) {
  1282. // if classname is null, the target class is THIS.
  1283. addPutstatic0(null, classname, fieldName, desc);
  1284. }
  1285. private void addPutstatic0(CtClass target, String classname,
  1286. String fieldName, String desc) {
  1287. add(PUTSTATIC);
  1288. // target is null if it represents THIS.
  1289. int ci = classname == null ? constPool.addClassInfo(target)
  1290. : constPool.addClassInfo(classname);
  1291. addIndex(constPool.addFieldrefInfo(ci, fieldName, desc));
  1292. growStack(-Descriptor.dataSize(desc));
  1293. }
  1294. /**
  1295. * Appends ARETURN, IRETURN, .., or RETURN.
  1296. *
  1297. * @param type the return type.
  1298. */
  1299. public void addReturn(CtClass type) {
  1300. if (type == null)
  1301. addOpcode(RETURN);
  1302. else if (type.isPrimitive()) {
  1303. CtPrimitiveType ptype = (CtPrimitiveType)type;
  1304. addOpcode(ptype.getReturnOp());
  1305. }
  1306. else
  1307. addOpcode(ARETURN);
  1308. }
  1309. /**
  1310. * Appends RET.
  1311. *
  1312. * @param var local variable
  1313. */
  1314. public void addRet(int var) {
  1315. if (var < 0x100) {
  1316. addOpcode(RET);
  1317. add(var);
  1318. }
  1319. else {
  1320. addOpcode(WIDE);
  1321. addOpcode(RET);
  1322. addIndex(var);
  1323. }
  1324. }
  1325. /**
  1326. * Appends instructions for executing
  1327. * <code>java.lang.System.println(<i>message</i>)</code>.
  1328. *
  1329. * @param message printed message.
  1330. */
  1331. public void addPrintln(String message) {
  1332. addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;");
  1333. addLdc(message);
  1334. addInvokevirtual("java.io.PrintStream",
  1335. "println", "(Ljava/lang/String;)V");
  1336. }
  1337. }