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

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