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.

ClassFileWriter.java 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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 java.io.DataOutputStream;
  18. import java.io.IOException;
  19. import java.io.OutputStream;
  20. /**
  21. * A quick class-file writer. This is useful when a generated
  22. * class file is simple and the code generation should be fast.
  23. *
  24. * <p>Example:
  25. *
  26. * <blockquote><pre>
  27. * ClassFileWriter cfw = new ClassFileWriter(ClassFile.JAVA_4, 0);
  28. * ConstPoolWriter cpw = cfw.getConstPool();
  29. *
  30. * FieldWriter fw = cfw.getFieldWriter();
  31. * fw.add(AccessFlag.PUBLIC, "value", "I", null);
  32. * fw.add(AccessFlag.PUBLIC, "value2", "J", null);
  33. *
  34. * int thisClass = cpw.addClassInfo("sample/Test");
  35. * int superClass = cpw.addClassInfo("java/lang/Object");
  36. *
  37. * MethodWriter mw = cfw.getMethodWriter();
  38. *
  39. * mw.begin(AccessFlag.PUBLIC, MethodInfo.nameInit, "()V", null, null);
  40. * mw.add(Opcode.ALOAD_0);
  41. * mw.add(Opcode.INVOKESPECIAL);
  42. * int signature = cpw.addNameAndTypeInfo(MethodInfo.nameInit, "()V");
  43. * mw.add16(cpw.addMethodrefInfo(superClass, signature));
  44. * mw.add(Opcode.RETURN);
  45. * mw.codeEnd(1, 1);
  46. * mw.end(null, null);
  47. *
  48. * mw.begin(AccessFlag.PUBLIC, "one", "()I", null, null);
  49. * mw.add(Opcode.ICONST_1);
  50. * mw.add(Opcode.IRETURN);
  51. * mw.codeEnd(1, 1);
  52. * mw.end(null, null);
  53. *
  54. * byte[] classfile = cfw.end(AccessFlag.PUBLIC, thisClass, superClass,
  55. * null, null);
  56. * </pre></blockquote>
  57. *
  58. * <p>The code above generates the following class:
  59. *
  60. * <blockquote><pre>
  61. * package sample;
  62. * public class Test {
  63. * public int value;
  64. * public long value2;
  65. * public Test() { super(); }
  66. * public one() { return 1; }
  67. * }
  68. * </pre></blockquote>
  69. *
  70. * @since 3.13
  71. */
  72. public class ClassFileWriter {
  73. private ByteStream output;
  74. private ConstPoolWriter constPool;
  75. private FieldWriter fields;
  76. private MethodWriter methods;
  77. int thisClass, superClass;
  78. /**
  79. * Constructs a class file writer.
  80. *
  81. * @param major the major version ({@link ClassFile#JAVA_4}, {@link ClassFile#JAVA_5}, ...).
  82. * @param minor the minor version (0 for JDK 1.3 and later).
  83. */
  84. public ClassFileWriter(int major, int minor) {
  85. output = new ByteStream(512);
  86. output.writeInt(0xCAFEBABE); // magic
  87. output.writeShort(minor);
  88. output.writeShort(major);
  89. constPool = new ConstPoolWriter(output);
  90. fields = new FieldWriter(constPool);
  91. methods = new MethodWriter(constPool);
  92. }
  93. /**
  94. * Returns a constant pool.
  95. */
  96. public ConstPoolWriter getConstPool() { return constPool; }
  97. /**
  98. * Returns a filed writer.
  99. */
  100. public FieldWriter getFieldWriter() { return fields; }
  101. /**
  102. * Returns a method writer.
  103. */
  104. public MethodWriter getMethodWriter() { return methods; }
  105. /**
  106. * Ends writing and returns the contents of the class file.
  107. *
  108. * @param accessFlags access flags.
  109. * @param thisClass this class. an index indicating its <code>CONSTANT_Class_info</code>.
  110. * @param superClass super class. an index indicating its <code>CONSTANT_Class_info</code>.
  111. * @param interfaces implemented interfaces.
  112. * index numbers indicating their <code>ClassInfo</code>.
  113. * It may be null.
  114. * @param aw attributes of the class file. May be null.
  115. *
  116. * @see AccessFlag
  117. */
  118. public byte[] end(int accessFlags, int thisClass, int superClass,
  119. int[] interfaces, AttributeWriter aw) {
  120. constPool.end();
  121. output.writeShort(accessFlags);
  122. output.writeShort(thisClass);
  123. output.writeShort(superClass);
  124. if (interfaces == null)
  125. output.writeShort(0);
  126. else {
  127. int n = interfaces.length;
  128. output.writeShort(n);
  129. for (int i = 0; i < n; i++)
  130. output.writeShort(interfaces[i]);
  131. }
  132. output.enlarge(fields.dataSize() + methods.dataSize() + 6);
  133. try {
  134. output.writeShort(fields.size());
  135. fields.write(output);
  136. output.writeShort(methods.numOfMethods());
  137. methods.write(output);
  138. }
  139. catch (IOException e) {}
  140. writeAttribute(output, aw, 0);
  141. return output.toByteArray();
  142. }
  143. /**
  144. * Ends writing and writes the contents of the class file into the
  145. * given output stream.
  146. *
  147. * @param accessFlags access flags.
  148. * @param thisClass this class. an index indicating its <code>CONSTANT_Class_info</code>.
  149. * @param superClass super class. an index indicating its <code>CONSTANT_Class_info</code>.
  150. * @param interfaces implemented interfaces.
  151. * index numbers indicating their <code>CONSTATNT_Class_info</code>.
  152. * It may be null.
  153. * @param aw attributes of the class file. May be null.
  154. *
  155. * @see AccessFlag
  156. */
  157. public void end(DataOutputStream out,
  158. int accessFlags, int thisClass, int superClass,
  159. int[] interfaces, AttributeWriter aw)
  160. throws IOException
  161. {
  162. constPool.end();
  163. output.writeTo(out);
  164. out.writeShort(accessFlags);
  165. out.writeShort(thisClass);
  166. out.writeShort(superClass);
  167. if (interfaces == null)
  168. out.writeShort(0);
  169. else {
  170. int n = interfaces.length;
  171. out.writeShort(n);
  172. for (int i = 0; i < n; i++)
  173. out.writeShort(interfaces[i]);
  174. }
  175. out.writeShort(fields.size());
  176. fields.write(out);
  177. out.writeShort(methods.numOfMethods());
  178. methods.write(out);
  179. if (aw == null)
  180. out.writeShort(0);
  181. else {
  182. out.writeShort(aw.size());
  183. aw.write(out);
  184. }
  185. }
  186. /**
  187. * This writes attributes.
  188. *
  189. * <p>For example, the following object writes a synthetic attribute:
  190. *
  191. * <pre>
  192. * ConstPoolWriter cpw = ...;
  193. * final int tag = cpw.addUtf8Info("Synthetic");
  194. * AttributeWriter aw = new AttributeWriter() {
  195. * public int size() {
  196. * return 1;
  197. * }
  198. * public void write(DataOutputStream out) throws java.io.IOException {
  199. * out.writeShort(tag);
  200. * out.writeInt(0);
  201. * }
  202. * };
  203. * </pre>
  204. */
  205. public static interface AttributeWriter {
  206. /**
  207. * Returns the number of attributes that this writer will
  208. * write.
  209. */
  210. public int size();
  211. /**
  212. * Writes all the contents of the attributes. The binary representation
  213. * of the contents is an array of <code>attribute_info</code>.
  214. */
  215. public void write(DataOutputStream out) throws IOException;
  216. }
  217. static void writeAttribute(ByteStream bs, AttributeWriter aw, int attrCount) {
  218. if (aw == null) {
  219. bs.writeShort(attrCount);
  220. return;
  221. }
  222. bs.writeShort(aw.size() + attrCount);
  223. DataOutputStream dos = new DataOutputStream(bs);
  224. try {
  225. aw.write(dos);
  226. dos.flush();
  227. }
  228. catch (IOException e) {}
  229. }
  230. /**
  231. * Field.
  232. */
  233. public static final class FieldWriter {
  234. protected ByteStream output;
  235. protected ConstPoolWriter constPool;
  236. private int fieldCount;
  237. FieldWriter(ConstPoolWriter cp) {
  238. output = new ByteStream(128);
  239. constPool = cp;
  240. fieldCount = 0;
  241. }
  242. /**
  243. * Adds a new field.
  244. *
  245. * @param accessFlags access flags.
  246. * @param name the field name.
  247. * @param descriptor the field type.
  248. * @param aw the attributes of the field. may be null.
  249. * @see AccessFlag
  250. */
  251. public void add(int accessFlags, String name, String descriptor, AttributeWriter aw) {
  252. int nameIndex = constPool.addUtf8Info(name);
  253. int descIndex = constPool.addUtf8Info(descriptor);
  254. add(accessFlags, nameIndex, descIndex, aw);
  255. }
  256. /**
  257. * Adds a new field.
  258. *
  259. * @param accessFlags access flags.
  260. * @param name the field name. an index indicating its <code>CONSTANT_Utf8_info</code>.
  261. * @param descriptor the field type. an index indicating its <code>CONSTANT_Utf8_info</code>.
  262. * @param aw the attributes of the field. may be null.
  263. * @see AccessFlag
  264. */
  265. public void add(int accessFlags, int name, int descriptor, AttributeWriter aw) {
  266. ++fieldCount;
  267. output.writeShort(accessFlags);
  268. output.writeShort(name);
  269. output.writeShort(descriptor);
  270. writeAttribute(output, aw, 0);
  271. }
  272. int size() { return fieldCount; }
  273. int dataSize() { return output.size(); }
  274. /**
  275. * Writes the added fields.
  276. */
  277. void write(OutputStream out) throws IOException {
  278. output.writeTo(out);
  279. }
  280. }
  281. /**
  282. * Method.
  283. */
  284. public static final class MethodWriter {
  285. protected ByteStream output;
  286. protected ConstPoolWriter constPool;
  287. private int methodCount;
  288. protected int codeIndex;
  289. protected int throwsIndex;
  290. protected int stackIndex;
  291. private int startPos;
  292. private boolean isAbstract;
  293. private int catchPos;
  294. private int catchCount;
  295. MethodWriter(ConstPoolWriter cp) {
  296. output = new ByteStream(256);
  297. constPool = cp;
  298. methodCount = 0;
  299. codeIndex = 0;
  300. throwsIndex = 0;
  301. stackIndex = 0;
  302. }
  303. /**
  304. * Starts Adding a new method.
  305. *
  306. * @param accessFlags access flags.
  307. * @param name the method name.
  308. * @param descriptor the method signature.
  309. * @param exceptions throws clause. It may be null.
  310. * The class names must be the JVM-internal
  311. * representations like <code>java/lang/Exception</code>.
  312. * @param aw attributes to the <code>Method_info</code>.
  313. */
  314. public void begin(int accessFlags, String name, String descriptor,
  315. String[] exceptions, AttributeWriter aw) {
  316. int nameIndex = constPool.addUtf8Info(name);
  317. int descIndex = constPool.addUtf8Info(descriptor);
  318. int[] intfs;
  319. if (exceptions == null)
  320. intfs = null;
  321. else
  322. intfs = constPool.addClassInfo(exceptions);
  323. begin(accessFlags, nameIndex, descIndex, intfs, aw);
  324. }
  325. /**
  326. * Starts adding a new method.
  327. *
  328. * @param accessFlags access flags.
  329. * @param name the method name. an index indicating its <code>CONSTANT_Utf8_info</code>.
  330. * @param descriptor the field type. an index indicating its <code>CONSTANT_Utf8_info</code>.
  331. * @param exceptions throws clause. indexes indicating <code>CONSTANT_Class_info</code>s.
  332. * It may be null.
  333. * @param aw attributes to the <code>Method_info</code>.
  334. */
  335. public void begin(int accessFlags, int name, int descriptor, int[] exceptions, AttributeWriter aw) {
  336. ++methodCount;
  337. output.writeShort(accessFlags);
  338. output.writeShort(name);
  339. output.writeShort(descriptor);
  340. isAbstract = (accessFlags & AccessFlag.ABSTRACT) != 0;
  341. int attrCount = isAbstract ? 0 : 1;
  342. if (exceptions != null)
  343. ++attrCount;
  344. writeAttribute(output, aw, attrCount);
  345. if (exceptions != null)
  346. writeThrows(exceptions);
  347. if (!isAbstract) {
  348. if (codeIndex == 0)
  349. codeIndex = constPool.addUtf8Info(CodeAttribute.tag);
  350. startPos = output.getPos();
  351. output.writeShort(codeIndex);
  352. output.writeBlank(12); // attribute_length, maxStack, maxLocals, code_lenth
  353. }
  354. catchPos = -1;
  355. catchCount = 0;
  356. }
  357. private void writeThrows(int[] exceptions) {
  358. if (throwsIndex == 0)
  359. throwsIndex = constPool.addUtf8Info(ExceptionsAttribute.tag);
  360. output.writeShort(throwsIndex);
  361. output.writeInt(exceptions.length * 2 + 2);
  362. output.writeShort(exceptions.length);
  363. for (int i = 0; i < exceptions.length; i++)
  364. output.writeShort(exceptions[i]);
  365. }
  366. /**
  367. * Appends an 8bit value of bytecode.
  368. *
  369. * @see Opcode
  370. */
  371. public void add(int b) {
  372. output.write(b);
  373. }
  374. /**
  375. * Appends a 16bit value of bytecode.
  376. */
  377. public void add16(int b) {
  378. output.writeShort(b);
  379. }
  380. /**
  381. * Appends a 32bit value of bytecode.
  382. */
  383. public void add32(int b) {
  384. output.writeInt(b);
  385. }
  386. /**
  387. * Appends a invokevirtual, inovkespecial, or invokestatic bytecode.
  388. *
  389. * @see Opcode
  390. */
  391. public void addInvoke(int opcode, String targetClass, String methodName,
  392. String descriptor) {
  393. int target = constPool.addClassInfo(targetClass);
  394. int nt = constPool.addNameAndTypeInfo(methodName, descriptor);
  395. int method = constPool.addMethodrefInfo(target, nt);
  396. add(opcode);
  397. add16(method);
  398. }
  399. /**
  400. * Ends appending bytecode.
  401. */
  402. public void codeEnd(int maxStack, int maxLocals) {
  403. if (!isAbstract) {
  404. output.writeShort(startPos + 6, maxStack);
  405. output.writeShort(startPos + 8, maxLocals);
  406. output.writeInt(startPos + 10, output.getPos() - startPos - 14); // code_length
  407. catchPos = output.getPos();
  408. catchCount = 0;
  409. output.writeShort(0); // number of catch clauses
  410. }
  411. }
  412. /**
  413. * Appends an <code>exception_table</code> entry to the
  414. * <code>Code_attribute</code>. This method is available
  415. * only after the <code>codeEnd</code> method is called.
  416. *
  417. * @param catchType an index indicating a <code>CONSTANT_Class_info</code>.
  418. */
  419. public void addCatch(int startPc, int endPc, int handlerPc, int catchType) {
  420. ++catchCount;
  421. output.writeShort(startPc);
  422. output.writeShort(endPc);
  423. output.writeShort(handlerPc);
  424. output.writeShort(catchType);
  425. }
  426. /**
  427. * Ends adding a new method. The <code>add</code> method must be
  428. * called before the <code>end</code> method is called.
  429. *
  430. * @param smap a stack map table. may be null.
  431. * @param aw attributes to the <code>Code_attribute</code>.
  432. * may be null.
  433. */
  434. public void end(StackMapTable.Writer smap, AttributeWriter aw) {
  435. if (isAbstract)
  436. return;
  437. // exception_table_length
  438. output.writeShort(catchPos, catchCount);
  439. int attrCount = smap == null ? 0 : 1;
  440. writeAttribute(output, aw, attrCount);
  441. if (smap != null) {
  442. if (stackIndex == 0)
  443. stackIndex = constPool.addUtf8Info(StackMapTable.tag);
  444. output.writeShort(stackIndex);
  445. byte[] data = smap.toByteArray();
  446. output.writeInt(data.length);
  447. output.write(data);
  448. }
  449. // Code attribute_length
  450. output.writeInt(startPos + 2, output.getPos() - startPos - 6);
  451. }
  452. /**
  453. * Returns the length of the bytecode that has been added so far.
  454. *
  455. * @return the length in bytes.
  456. * @since 3.19
  457. */
  458. public int size() { return output.getPos() - startPos - 14; }
  459. int numOfMethods() { return methodCount; }
  460. int dataSize() { return output.size(); }
  461. /**
  462. * Writes the added methods.
  463. */
  464. void write(OutputStream out) throws IOException {
  465. output.writeTo(out);
  466. }
  467. }
  468. /**
  469. * Constant Pool.
  470. */
  471. public static final class ConstPoolWriter {
  472. ByteStream output;
  473. protected int startPos;
  474. protected int num;
  475. ConstPoolWriter(ByteStream out) {
  476. output = out;
  477. startPos = out.getPos();
  478. num = 1;
  479. output.writeShort(1); // number of entries
  480. }
  481. /**
  482. * Makes <code>CONSTANT_Class_info</code> objects for each class name.
  483. *
  484. * @return an array of indexes indicating <code>CONSTANT_Class_info</code>s.
  485. */
  486. public int[] addClassInfo(String[] classNames) {
  487. int n = classNames.length;
  488. int[] result = new int[n];
  489. for (int i = 0; i < n; i++)
  490. result[i] = addClassInfo(classNames[i]);
  491. return result;
  492. }
  493. /**
  494. * Adds a new <code>CONSTANT_Class_info</code> structure.
  495. *
  496. * <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
  497. * for storing the class name.
  498. *
  499. * @param jvmname the JVM-internal representation of a class name.
  500. * e.g. <code>java/lang/Object</code>.
  501. * @return the index of the added entry.
  502. */
  503. public int addClassInfo(String jvmname) {
  504. int utf8 = addUtf8Info(jvmname);
  505. output.write(ClassInfo.tag);
  506. output.writeShort(utf8);
  507. return num++;
  508. }
  509. /**
  510. * Adds a new <code>CONSTANT_Class_info</code> structure.
  511. *
  512. * @param name <code>name_index</code>
  513. * @return the index of the added entry.
  514. */
  515. public int addClassInfo(int name) {
  516. output.write(ClassInfo.tag);
  517. output.writeShort(name);
  518. return num++;
  519. }
  520. /**
  521. * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
  522. *
  523. * @param name <code>name_index</code>
  524. * @param type <code>descriptor_index</code>
  525. * @return the index of the added entry.
  526. */
  527. public int addNameAndTypeInfo(String name, String type) {
  528. return addNameAndTypeInfo(addUtf8Info(name), addUtf8Info(type));
  529. }
  530. /**
  531. * Adds a new <code>CONSTANT_NameAndType_info</code> structure.
  532. *
  533. * @param name <code>name_index</code>
  534. * @param type <code>descriptor_index</code>
  535. * @return the index of the added entry.
  536. */
  537. public int addNameAndTypeInfo(int name, int type) {
  538. output.write(NameAndTypeInfo.tag);
  539. output.writeShort(name);
  540. output.writeShort(type);
  541. return num++;
  542. }
  543. /**
  544. * Adds a new <code>CONSTANT_Fieldref_info</code> structure.
  545. *
  546. * @param classInfo <code>class_index</code>
  547. * @param nameAndTypeInfo <code>name_and_type_index</code>.
  548. * @return the index of the added entry.
  549. */
  550. public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) {
  551. output.write(FieldrefInfo.tag);
  552. output.writeShort(classInfo);
  553. output.writeShort(nameAndTypeInfo);
  554. return num++;
  555. }
  556. /**
  557. * Adds a new <code>CONSTANT_Methodref_info</code> structure.
  558. *
  559. * @param classInfo <code>class_index</code>
  560. * @param nameAndTypeInfo <code>name_and_type_index</code>.
  561. * @return the index of the added entry.
  562. */
  563. public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) {
  564. output.write(MethodrefInfo.tag);
  565. output.writeShort(classInfo);
  566. output.writeShort(nameAndTypeInfo);
  567. return num++;
  568. }
  569. /**
  570. * Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
  571. * structure.
  572. *
  573. * @param classInfo <code>class_index</code>
  574. * @param nameAndTypeInfo <code>name_and_type_index</code>.
  575. * @return the index of the added entry.
  576. */
  577. public int addInterfaceMethodrefInfo(int classInfo,
  578. int nameAndTypeInfo) {
  579. output.write(InterfaceMethodrefInfo.tag);
  580. output.writeShort(classInfo);
  581. output.writeShort(nameAndTypeInfo);
  582. return num++;
  583. }
  584. /**
  585. * Adds a new <code>CONSTANT_MethodHandle_info</code>
  586. * structure.
  587. *
  588. * @param kind <code>reference_kind</code>
  589. * such as {@link ConstPool#REF_invokeStatic <code>REF_invokeStatic</code>}.
  590. * @param index <code>reference_index</code>.
  591. * @return the index of the added entry.
  592. *
  593. * @since 3.17.1
  594. */
  595. public int addMethodHandleInfo(int kind, int index) {
  596. output.write(MethodHandleInfo.tag);
  597. output.write(kind);
  598. output.writeShort(index);
  599. return num++;
  600. }
  601. /**
  602. * Adds a new <code>CONSTANT_MethodType_info</code>
  603. * structure.
  604. *
  605. * @param desc <code>descriptor_index</code>.
  606. * @return the index of the added entry.
  607. *
  608. * @since 3.17.1
  609. */
  610. public int addMethodTypeInfo(int desc) {
  611. output.write(MethodTypeInfo.tag);
  612. output.writeShort(desc);
  613. return num++;
  614. }
  615. /**
  616. * Adds a new <code>CONSTANT_InvokeDynamic_info</code>
  617. * structure.
  618. *
  619. * @param bootstrap <code>bootstrap_method_attr_index</code>.
  620. * @param nameAndTypeInfo <code>name_and_type_index</code>.
  621. * @return the index of the added entry.
  622. *
  623. * @since 3.17.1
  624. */
  625. public int addInvokeDynamicInfo(int bootstrap,
  626. int nameAndTypeInfo) {
  627. output.write(InvokeDynamicInfo.tag);
  628. output.writeShort(bootstrap);
  629. output.writeShort(nameAndTypeInfo);
  630. return num++;
  631. }
  632. /**
  633. * Adds a new <code>CONSTANT_String_info</code>
  634. * structure.
  635. *
  636. * <p>This also adds a new <code>CONSTANT_Utf8_info</code>
  637. * structure.
  638. *
  639. * @return the index of the added entry.
  640. */
  641. public int addStringInfo(String str) {
  642. int utf8 = addUtf8Info(str);
  643. output.write(StringInfo.tag);
  644. output.writeShort(utf8);
  645. return num++;
  646. }
  647. /**
  648. * Adds a new <code>CONSTANT_Integer_info</code>
  649. * structure.
  650. *
  651. * @return the index of the added entry.
  652. */
  653. public int addIntegerInfo(int i) {
  654. output.write(IntegerInfo.tag);
  655. output.writeInt(i);
  656. return num++;
  657. }
  658. /**
  659. * Adds a new <code>CONSTANT_Float_info</code>
  660. * structure.
  661. *
  662. * @return the index of the added entry.
  663. */
  664. public int addFloatInfo(float f) {
  665. output.write(FloatInfo.tag);
  666. output.writeFloat(f);
  667. return num++;
  668. }
  669. /**
  670. * Adds a new <code>CONSTANT_Long_info</code>
  671. * structure.
  672. *
  673. * @return the index of the added entry.
  674. */
  675. public int addLongInfo(long l) {
  676. output.write(LongInfo.tag);
  677. output.writeLong(l);
  678. int n = num;
  679. num += 2;
  680. return n;
  681. }
  682. /**
  683. * Adds a new <code>CONSTANT_Double_info</code>
  684. * structure.
  685. *
  686. * @return the index of the added entry.
  687. */
  688. public int addDoubleInfo(double d) {
  689. output.write(DoubleInfo.tag);
  690. output.writeDouble(d);
  691. int n = num;
  692. num += 2;
  693. return n;
  694. }
  695. /**
  696. * Adds a new <code>CONSTANT_Utf8_info</code>
  697. * structure.
  698. *
  699. * @return the index of the added entry.
  700. */
  701. public int addUtf8Info(String utf8) {
  702. output.write(Utf8Info.tag);
  703. output.writeUTF(utf8);
  704. return num++;
  705. }
  706. /**
  707. * Writes the contents of this class pool.
  708. */
  709. void end() {
  710. output.writeShort(startPos, num);
  711. }
  712. }
  713. }