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.

tutorial.html 41KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  4. <title>Javassist Tutorial</title>
  5. <link rel="stylesheet" type="text/css" href="brown.css">
  6. </head>
  7. <body>
  8. <b>
  9. <font size="+3">
  10. Getting Started with Javassist
  11. </font>
  12. <p><font size="+2">
  13. Shigeru Chiba
  14. </font>
  15. </b>
  16. <p><div align="right"><a href="tutorial2.html">Next page</a></div>
  17. <ul>1. <a href="#read">Reading and writing bytecode</a>
  18. <br>2. <a href="#pool">ClassPool</a>
  19. <br>3. <a href="#load">Class loader</a>
  20. <br>4. <a href="tutorial2.html#intro">Introspection and customization</a>
  21. <br>5. <a href="tutorial3.html#intro">Bytecode level API</a>
  22. <br>6. <a href="tutorial3.html#generics">Generics</a>
  23. <br>7. <a href="tutorial3.html#varargs">Varargs</a>
  24. <br>8. <a href="tutorial3.html#j2me">J2ME</a>
  25. <br>9. <a href="tutorial3.html#debug">Debug</a>
  26. </ul>
  27. <p><br>
  28. <a name="read">
  29. <h2>1. Reading and writing bytecode</h2>
  30. <p>Javassist is a class library for dealing with Java bytecode.
  31. Java bytecode is stored in a binary file called a class file.
  32. Each class file contains one Java class or interface.
  33. <p>The class <code>Javassist.CtClass</code> is an absatract
  34. representation of a class file. A <code>CtClass</code> (compile-time
  35. class) object is a handle for dealing with a class file. The
  36. following program is a very simple example:
  37. <ul><pre>
  38. ClassPool pool = ClassPool.getDefault();
  39. CtClass cc = pool.get("test.Rectangle");
  40. cc.setSuperclass(pool.get("test.Point"));
  41. cc.writeFile();
  42. </pre></ul>
  43. <p>This program first obtains a <code>ClassPool</code> object, which
  44. controls bytecode modification with Javassist. The
  45. <code>ClassPool</code> object is a container of <code>CtClass</code>
  46. object representing a class file. It reads a class file on demand for
  47. constructing a <code>CtClass</code> object and records the
  48. constructed object for responding later accesses.
  49. To modify the definition of a class, the users must first obtain
  50. from a <code>ClassPool</code> object
  51. a reference to a <code>CtClass</code> object representing that class.
  52. <code>get()</code> in <code>ClassPool</code> is used for this purpose.
  53. In the case of the program shown above, the
  54. <code>CtClass</code> object representing a class
  55. <code>test.Rectangle</code> is obtained from the
  56. <code>ClassPool</code> object and it is assigned to a variable
  57. <code>cc</code>.
  58. The <code>ClassPool</code> object returned by <code>getDfault()</code>
  59. searches the default system search path.
  60. <p>From the implementation viewpoint, <code>ClassPool</code> is a hash
  61. table of <code>CtClass</code> objects, which uses the class names as
  62. keys. <code>get()</code> in <code>ClassPool</code> searches this hash
  63. table to find a <code>CtClass</code> object associated with the
  64. specified key. If such a <code>CtClass</code> object is not found,
  65. <code>get()</code> reads a class file to construct a new
  66. <code>CtClass</code> object, which is recorded in the hash table and
  67. then returned as the resulting value of <code>get()</code>.
  68. <p>The <code>CtClass</code> object obtained from a <code>ClassPool</code>
  69. object can be modified
  70. (<a href="tutorial2.html#intro">details of how to modify
  71. a <code>CtClass</code></a> will be presented later).
  72. In the example above, it is modified so that the superclass of
  73. <code>test.Rectangle</code> is changed into a class
  74. <code>test.Point</code>. This change is reflected on the original
  75. class file when <code>writeFile()</code> in <code>CtClass()</code> is
  76. finally called.
  77. <p><code>writeFile()</code> translates the <code>CtClass</code> object
  78. into a class file and writes it on a local disk.
  79. Javassist also provides a method for directly obtaining the
  80. modified bytecode. To obtain the bytecode, call <code>toBytecode()</code>:
  81. <ul><pre>
  82. byte[] b = cc.toBytecode();
  83. </pre></ul>
  84. <p>You can directly load the <code>CtClass</code> as well:
  85. <ul><pre>
  86. Class clazz = cc.toClass();
  87. </pre></ul>
  88. <p><code>toClass()</code> requests the context class loader for the current
  89. thread to load the class file represented by the <code>CtClass</code>. It
  90. returns a <code>java.lang.Class</code> object representing the loaded class.
  91. For more details, please see <a href="#toclass">this section below</a>.
  92. <a name="def">
  93. <h4>Defining a new class</h4>
  94. <p>To define a new class from scratch, <code>makeClass()</code>
  95. must be called on a <code>ClassPool</code>.
  96. <ul><pre>
  97. ClassPool pool = ClassPool.getDefault();
  98. CtClass cc = pool.makeClass("Point");
  99. </pre></ul>
  100. <p>This program defines a class <code>Point</code>
  101. including no members.
  102. Member methods of <code>Point</code> can be created with
  103. factory methods declared in <code>CtNewMethod</code> and
  104. appended to <code>Point</code> with <code>addMethod()</code>
  105. in <code>CtClass</code>.
  106. <p><code>makeClass()</code> cannot create a new interface;
  107. <code>makeInterface()</code> in <code>ClassPool</code> can do.
  108. Member methods in an interface can be created with
  109. <code>abstractMethod()</code> in <code>CtNewMethod</code>.
  110. Note that an interface method is an abstract method.
  111. <a name="frozenclasses">
  112. <h4>Frozen classes</h4></a>
  113. <p>If a <code>CtClass</code> object is converted into a class file by
  114. <code>writeFile()</code>, <code>toClass()</code>, or
  115. <code>toBytecode()</code>, Javassist freezes that <code>CtClass</code>
  116. object. Further modifications of that <code>CtClass</code> object are
  117. not permitted. This is for warning the developers when they attempt
  118. to modify a class file that has been already loaded since the JVM does
  119. not allow reloading a class.
  120. <p>A frozen <code>CtClass</code> can be defrost so that
  121. modifications of the class definition will be permitted. For example,
  122. <ul><pre>
  123. CtClasss cc = ...;
  124. :
  125. cc.writeFile();
  126. cc.defrost();
  127. cc.setSuperclass(...); // OK since the class is not frozen.
  128. </pre></ul>
  129. <p>After <code>defrost()</code> is called, the <code>CtClass</code>
  130. object can be modified again.
  131. <p>If <code>ClassPool.doPruning</code> is set to <code>true</code>,
  132. then Javassist prunes the data structure contained
  133. in a <code>CtClass</code> object
  134. when Javassist freezes that object.
  135. To reduce memory
  136. consumption, pruning discards unnecessary attributes
  137. (<code>attribute_info</code> structures) in that object.
  138. For example, <code>Code_attribute</code> structures (method bodies)
  139. are discarded.
  140. Thus, after a
  141. <code>CtClass</code> object is pruned, the bytecode of a method is not
  142. accessible except method names, signatures, and annotations.
  143. The pruned <code>CtClass</code> object cannot be defrost again.
  144. The default value of <code>ClassPool.doPruning</code> is <code>false</code>.
  145. <p>To disallow pruning a particular <code>CtClass</code>,
  146. <code>stopPruning()</code> must be called on that object in advance:
  147. <ul><pre>
  148. CtClasss cc = ...;
  149. cc.stopPruning(true);
  150. :
  151. cc.writeFile(); // convert to a class file.
  152. // cc is not pruned.
  153. </pre></ul>
  154. <p>The <code>CtClass</code> object <code>cc</code> is not pruned.
  155. Thus it can be defrost after <code>writeFile()</code> is called.
  156. <ul><b>Note:</b>
  157. While debugging, you might want to temporarily stop pruning and freezing
  158. and write a modified class file to a disk drive.
  159. <code>debugWriteFile()</code> is a convenient method
  160. for that purpose. It stops pruning, writes a class file, defrosts it,
  161. and turns pruning on again (if it was initially on).
  162. </ul>
  163. <h4>Class search path</h4>
  164. <p>The default <code>ClassPool</code> returned
  165. by a static method <code>ClassPool.getDefault()</code>
  166. searches the same path that the underlying JVM (Java virtual machine) has.
  167. <em>If a program is running on a web application server such as JBoss and Tomcat,
  168. the <code>ClassPool</code> object may not be able to find user classes</em>
  169. since such a web application server uses multiple class loaders as well as
  170. the system class loader. In that case, an additional class path must be
  171. registered to the <code>ClassPool</code>. Suppose that <code>pool</code>
  172. refers to a <code>ClassPool</code> object:
  173. <ul><pre>
  174. pool.insertClassPath(new ClassClassPath(this.getClass()));
  175. </pre></ul>
  176. <p>
  177. This statement registers the class path that was used for loading
  178. the class of the object that <code>this</code> refers to.
  179. You can use any <code>Class</code> object as an argument instead of
  180. <code>this.getClass()</code>. The class path used for loading the
  181. class represented by that <code>Class</code> object is registered.
  182. <p>
  183. You can register a directory name as the class search path.
  184. For example, the following code adds a directory
  185. <code>/usr/local/javalib</code>
  186. to the search path:
  187. <ul><pre>
  188. ClassPool pool = ClassPool.getDefault();
  189. pool.insertClassPath("/usr/local/javalib");
  190. </pre></ul>
  191. <p>The search path that the users can add is not only a directory but also
  192. a URL:
  193. <ul><pre>
  194. ClassPool pool = ClassPool.getDefault();
  195. ClassPath cp = new URLClassPath("www.javassist.org", 80, "/java/", "org.javassist.");
  196. pool.insertClassPath(cp);
  197. </pre></ul>
  198. <p>This program adds "http://www.javassist.org:80/java/" to the class search
  199. path. This URL is used only for searching classes belonging to a
  200. package <code>org.javassist</code>. For example, to load a class
  201. <code>org.javassist.test.Main</code>, its class file will be obtained from:
  202. <ul><pre>http://www.javassist.org:80/java/org/javassist/test/Main.class
  203. </pre></ul>
  204. <p>Furthermore, you can directly give a byte array
  205. to a <code>ClassPool</code> object
  206. and construct a <code>CtClass</code> object from that array. To do this,
  207. use <code>ByteArrayClassPath</code>. For example,
  208. <ul><pre>
  209. ClassPool cp = ClassPool.getDefault();
  210. byte[] b = <em>a byte array</em>;
  211. String name = <em>class name</em>;
  212. cp.insertClassPath(new ByteArrayClassPath(name, b));
  213. CtClass cc = cp.get(name);
  214. </pre></ul>
  215. <p>The obtained <code>CtClass</code> object represents
  216. a class defined by the class file specified by <code>b</code>.
  217. The <code>ClassPool</code> reads a class file from the given
  218. <code>ByteArrayClassPath</code> if <code>get()</code> is called
  219. and the class name given to <code>get()</code> is equal to
  220. one specified by <code>name</code>.
  221. <p>If you do not know the fully-qualified name of the class, then you
  222. can use <code>makeClass()</code> in <code>ClassPool</code>:
  223. <ul><pre>
  224. ClassPool cp = ClassPool.getDefault();
  225. InputStream ins = <em>an input stream for reading a class file</em>;
  226. CtClass cc = cp.makeClass(ins);
  227. </pre></ul>
  228. <p><code>makeClass()</code> returns the <code>CtClass</code> object
  229. constructed from the given input stream. You can use
  230. <code>makeClass()</code> for eagerly feeding class files to
  231. the <code>ClassPool</code> object. This might improve performance
  232. if the search path includes a large jar file. Since
  233. a <code>ClassPool</code> object reads a class file on demand,
  234. it might repeatedly search the whole jar file for every class file.
  235. <code>makeClass()</code> can be used for optimizing this search.
  236. The <code>CtClass</code> constructed by <code>makeClass()</code>
  237. is kept in the <code>ClassPool</code> object and the class file is never
  238. read again.
  239. <p>The users can extend the class search path. They can define a new
  240. class implementing <code>ClassPath</code> interface and give an
  241. instance of that class to <code>insertClassPath()</code> in
  242. <code>ClassPool</code>. This allows a non-standard resource to be
  243. included in the search path.
  244. <p><br>
  245. <a name="pool">
  246. <h2>2. ClassPool</h2>
  247. <p>
  248. A <code>ClassPool</code> object is a container of <code>CtClass</code>
  249. objects. Once a <code>CtClass</code> object is created, it is
  250. recorded in a <code>ClassPool</code> for ever. This is because a
  251. compiler may need to access the <code>CtClass</code> object later when
  252. it compiles source code that refers to the class represented by that
  253. <code>CtClass</code>.
  254. <p>
  255. For example, suppose that a new method <code>getter()</code> is added
  256. to a <code>CtClass</code> object representing <code>Point</code>
  257. class. Later, the program attempts to compile source code including a
  258. method call to <code>getter()</code> in <code>Point</code> and use the
  259. compiled code as the body of a method, which will be added to another
  260. class <code>Line</code>. If the <code>CtClass</code> object representing
  261. <code>Point</code> is lost, the compiler cannot compile the method call
  262. to <code>getter()</code>. Note that the original class definition does
  263. not include <code>getter()</code>. Therefore, to correctly compile
  264. such a method call, the <code>ClassPool</code>
  265. must contain all the instances of <code>CtClass</code> all the time of
  266. program execution.
  267. <a name="avoidmemory">
  268. <h4>Avoid out of memory</h4>
  269. </a>
  270. <p>
  271. This specification of <code>ClassPool</code> may cause huge memory
  272. consumption if the number of <code>CtClass</code> objects becomes
  273. amazingly large (this rarely happens since Javassist tries to reduce
  274. memory consumption in <a href="#frozenclasses">various ways</a>).
  275. To avoid this problem, you
  276. can explicitly remove an unnecessary <code>CtClass</code> object from
  277. the <code>ClassPool</code>. If you call <code>detach()</code> on a
  278. <code>CtClass</code> object, then that <code>CtClass</code> object is
  279. removed from the <code>ClassPool</code>. For example,
  280. <ul><pre>
  281. CtClass cc = ... ;
  282. cc.writeFile();
  283. cc.detach();
  284. </pre></ul>
  285. <p>You must not call any method on that
  286. <code>CtClass</code> object after <code>detach()</code> is called.
  287. However, you can call <code>get()</code> on <code>ClassPool</code>
  288. to make a new instance of <code>CtClass</code> representing
  289. the same class. If you call <code>get()</code>, the <code>ClassPool</code>
  290. reads a class file again and newly creates a <code>CtClass</code>
  291. object, which is returned by <code>get()</code>.
  292. <p>
  293. Another idea is to occasionally replace a <code>ClassPool</code> with
  294. a new one and discard the old one. If an old <code>ClassPool</code>
  295. is garbage collected, the <code>CtClass</code> objects included in
  296. that <code>ClassPool</code> are also garbage collected.
  297. To create a new instance of <code>ClassPool</code>, execute the following
  298. code snippet:
  299. <ul><pre>
  300. ClassPool cp = new ClassPool(true);
  301. // if needed, append an extra search path by appendClassPath()
  302. </pre></ul>
  303. <p>This creates a <code>ClassPool</code> object that behaves as the
  304. default <code>ClassPool</code> returned by
  305. <code>ClassPool.getDefault()</code> does.
  306. Note that <code>ClassPool.getDefault()</code> is a singleton factory method
  307. provided for convenience. It creates a <code>ClassPool</code> object in
  308. the same way shown above although it keeps a single instance of
  309. <code>ClassPool</code> and reuses it.
  310. A <code>ClassPool</code> object returned by <code>getDefault()</code>
  311. does not have a special role. <code>getDefault()</code> is a convenience
  312. method.
  313. <p>Note that <code>new ClassPool(true)</code> is a convenient constructor,
  314. which constructs a <code>ClassPool</code> object and appends the system
  315. search path to it. Calling that constructor is
  316. equivalent to the following code:
  317. <ul><pre>
  318. ClassPool cp = new ClassPool();
  319. cp.appendSystemPath(); // or append another path by appendClassPath()
  320. </pre></ul>
  321. <h4>Cascaded ClassPools</h4>
  322. <p>
  323. <em>If a program is running on a web application server,</em>
  324. creating multiple instances of <code>ClassPool</code> might be necessary;
  325. an instance of <code>ClassPool</code> should be created
  326. for each class loader (i.e. container).
  327. The program should create a <code>ClassPool</code> object by not calling
  328. <code>getDefault()</code> but a constructor of <code>ClassPool</code>.
  329. <p>
  330. Multiple <code>ClassPool</code> objects can be cascaded like
  331. <code>java.lang.ClassLoader</code>. For example,
  332. <ul><pre>
  333. ClassPool parent = ClassPool.getDefault();
  334. ClassPool child = new ClassPool(parent);
  335. child.insertClassPath("./classes");
  336. </pre></ul>
  337. <p>
  338. If <code>child.get()</code> is called, the child <code>ClassPool</code>
  339. first delegates to the parent <code>ClassPool</code>. If the parent
  340. <code>ClassPool</code> fails to find a class file, then the child
  341. <code>ClassPool</code> attempts to find a class file
  342. under the <code>./classes</code> directory.
  343. <p>
  344. If <code>child.childFirstLookup</code> is true, the child
  345. <code>ClassPool</code> attempts to find a class file before delegating
  346. to the parent <code>ClassPool</code>. For example,
  347. <ul><pre>
  348. ClassPool parent = ClassPool.getDefault();
  349. ClassPool child = new ClassPool(parent);
  350. child.appendSystemPath(); // the same class path as the default one.
  351. child.childFirstLookup = true; // changes the behavior of the child.
  352. </pre></ul>
  353. <h4>Changing a class name for defining a new class</h4>
  354. <p>A new class can be defined as a copy of an existing class.
  355. The program below does that:
  356. <ul><pre>
  357. ClassPool pool = ClassPool.getDefault();
  358. CtClass cc = pool.get("Point");
  359. cc.setName("Pair");
  360. </pre></ul>
  361. <p>This program first obtains the <code>CtClass</code> object for
  362. class <code>Point</code>. Then it calls <code>setName()</code> to
  363. give a new name <code>Pair</code> to that <code>CtClass</code> object.
  364. After this call, all occurrences of the class name in the class
  365. definition represented by that <code>CtClass</code> object are changed
  366. from <code>Point</code> to <code>Pair</code>. The other part of the
  367. class definition does not change.
  368. <p>Note that <code>setName()</code> in <code>CtClass</code> changes a
  369. record in the <code>ClassPool</code> object. From the implementation
  370. viewpoint, a <code>ClassPool</code> object is a hash table of
  371. <code>CtClass</code> objects. <code>setName()</code> changes
  372. the key associated to the <code>CtClass</code> object in the hash
  373. table. The key is changed from the original class name to the new
  374. class name.
  375. <p>Therefore, if <code>get("Point")</code> is later called on the
  376. <code>ClassPool</code> object again, then it never returns the
  377. <code>CtClass</code> object that the variable <code>cc</code> refers to.
  378. The <code>ClassPool</code> object reads
  379. a class file
  380. <code>Point.class</code> again and it constructs a new <code>CtClass</code>
  381. object for class <code>Point</code>.
  382. This is because the <code>CtClass</code> object associated with the name
  383. <code>Point</code> does not exist any more.
  384. See the followings:
  385. <ul><pre>
  386. ClassPool pool = ClassPool.getDefault();
  387. CtClass cc = pool.get("Point");
  388. CtClass cc1 = pool.get("Point"); // cc1 is identical to cc.
  389. cc.setName("Pair");
  390. CtClass cc2 = pool.get("Pair"); // cc2 is identical to cc.
  391. CtClass cc3 = pool.get("Point"); // cc3 is not identical to cc.
  392. </pre></ul>
  393. <p><code>cc1</code> and <code>cc2</code> refer to the same instance of
  394. <code>CtClass</code> that <code>cc</code> does whereas
  395. <code>cc3</code> does not. Note that, after
  396. <code>cc.setName("Pair")</code> is executed, the <code>CtClass</code>
  397. object that <code>cc</code> and <code>cc1</code> refer to represents
  398. the <code>Pair</code> class.
  399. <p>The <code>ClassPool</code> object is used to maintain one-to-one
  400. mapping between classes and <code>CtClass</code> objects. Javassist
  401. never allows two distinct <code>CtClass</code> objects to represent
  402. the same class unless two independent <code>ClassPool</code> are created.
  403. This is a significant feature for consistent program
  404. transformation.
  405. <p>To create another copy of the default instance of
  406. <code>ClassPool</code>, which is returned by
  407. <code>ClassPool.getDefault()</code>, execute the following code
  408. snippet (this code was already <a href="#avoidmemory">shown above</a>):
  409. <ul><pre>
  410. ClassPool cp = new ClassPool(true);
  411. </pre></ul>
  412. <p>If you have two <code>ClassPool</code> objects, then you can
  413. obtain, from each <code>ClassPool</code>, a distinct
  414. <code>CtClass</code> object representing the same class file. You can
  415. differently modify these <code>CtClass</code> objects to generate
  416. different versions of the class.
  417. <h4>Renaming a frozen class for defining a new class</h4>
  418. <p>Once a <code>CtClass</code> object is converted into a class file
  419. by <code>writeFile()</code> or <code>toBytecode()</code>, Javassist
  420. rejects further modifications of that <code>CtClass</code> object.
  421. Hence, after the <code>CtClass</code> object representing <code>Point</code>
  422. class is converted into a class file, you cannot define <code>Pair</code>
  423. class as a copy of <code>Point</code> since executing <code>setName()</code>
  424. on <code>Point</code> is rejected.
  425. The following code snippet is wrong:
  426. <ul><pre>
  427. ClassPool pool = ClassPool.getDefault();
  428. CtClass cc = pool.get("Point");
  429. cc.writeFile();
  430. cc.setName("Pair"); // wrong since writeFile() has been called.
  431. </pre></ul>
  432. <p>To avoid this restriction, you should call <code>getAndRename()</code>
  433. in <code>ClassPool</code>. For example,
  434. <ul><pre>
  435. ClassPool pool = ClassPool.getDefault();
  436. CtClass cc = pool.get("Point");
  437. cc.writeFile();
  438. CtClass cc2 = pool.getAndRename("Point", "Pair");
  439. </pre></ul>
  440. <p>If <code>getAndRename()</code> is called, the <code>ClassPool</code>
  441. first reads <code>Point.class</code> for creating a new <code>CtClass</code>
  442. object representing <code>Point</code> class. However, it renames that
  443. <code>CtClass</code> object from <code>Point</code> to <code>Pair</code> before
  444. it records that <code>CtClass</code> object in a hash table.
  445. Thus <code>getAndRename()</code>
  446. can be executed after <code>writeFile()</code> or <code>toBytecode()</code>
  447. is called on the the <code>CtClass</code> object representing <code>Point</code>
  448. class.
  449. <p><br>
  450. <a name="load">
  451. <h2>3. Class loader</h2>
  452. <p>If what classes must be modified is known in advance,
  453. the easiest way for modifying the classes is as follows:
  454. <ul><li>1. Get a <code>CtClass</code> object by calling
  455. <code>ClassPool.get()</code>,
  456. <li>2. Modify it, and
  457. <li>3. Call <code>writeFile()</code> or <code>toBytecode()</code>
  458. on that <code>CtClass</code> object to obtain a modified class file.
  459. </ul>
  460. <p>If whether a class is modified or not is determined at load time,
  461. the users must make Javassist collaborate with a class loader.
  462. Javassist can be used with a class loader so that bytecode can be
  463. modified at load time. The users of Javassist can define their own
  464. version of class loader but they can also use a class loader provided
  465. by Javassist.
  466. <p><br>
  467. <a name="toclass">
  468. <h3>3.1 The <code>toClass</code> method in <code>CtClass</code></h3>
  469. </a>
  470. <p>The <code>CtClass</code> provides a convenience method
  471. <code>toClass()</code>, which requests the context class loader for
  472. the current thread to load the class represented by the <code>CtClass</code>
  473. object. To call this method, the caller must have appropriate permission;
  474. otherwise, a <code>SecurityException</code> may be thrown.
  475. <p>The following program shows how to use <code>toClass()</code>:
  476. <ul><pre>
  477. public class Hello {
  478. public void say() {
  479. System.out.println("Hello");
  480. }
  481. }
  482. public class Test {
  483. public static void main(String[] args) throws Exception {
  484. ClassPool cp = ClassPool.getDefault();
  485. CtClass cc = cp.get("Hello");
  486. CtMethod m = cc.getDeclaredMethod("say");
  487. m.insertBefore("{ System.out.println(\"Hello.say():\"); }");
  488. Class c = cc.toClass();
  489. Hello h = (Hello)c.newInstance();
  490. h.say();
  491. }
  492. }
  493. </pre></ul>
  494. <p><code>Test.main()</code> inserts a call to <code>println()</code>
  495. in the method body of <code>say()</code> in <code>Hello</code>. Then
  496. it constructs an instance of the modified <code>Hello</code> class
  497. and calls <code>say()</code> on that instance.
  498. <p>Note that the program above depends on the fact that the
  499. <code>Hello</code> class is never loaded before <code>toClass()</code>
  500. is invoked. If not, the JVM would load the original
  501. <code>Hello</code> class before <code>toClass()</code> requests to
  502. load the modified <code>Hello</code> class. Hence loading the
  503. modified <code>Hello</code> class would be failed
  504. (<code>LinkageError</code> is thrown). For example, if
  505. <code>main()</code> in <code>Test</code> is something like this:
  506. <ul><pre>
  507. public static void main(String[] args) throws Exception {
  508. Hello orig = new Hello();
  509. ClassPool cp = ClassPool.getDefault();
  510. CtClass cc = cp.get("Hello");
  511. :
  512. }
  513. </pre></ul>
  514. <p>then the original <code>Hello</code> class is loaded at the first
  515. line of <code>main</code> and the call to <code>toClass()</code>
  516. throws an exception since the class loader cannot load two different
  517. versions of the <code>Hello</code> class at the same time.
  518. <p><em>If the program is running on some application server such as
  519. JBoss and Tomcat,</em> the context class loader used by
  520. <code>toClass()</code> might be inappropriate. In this case, you
  521. would see an unexpected <code>ClassCastException</code>. To avoid
  522. this exception, you must explicitly give an appropriate class loader
  523. to <code>toClass()</code>. For example, if <code>bean</code> is your
  524. session bean object, then the following code:
  525. <ul><pre>CtClass cc = ...;
  526. Class c = cc.toClass(bean.getClass().getClassLoader());
  527. </pre></ul>
  528. <p>would work. You should give <code>toClass()</code> the class loader
  529. that has loaded your program (in the above example, the class of
  530. the <code>bean</code> object).
  531. <p><code>toClass()</code> is provided for convenience. If you need
  532. more complex functionality, you should write your own class loader.
  533. <p><br>
  534. <h3>3.2 Class loading in Java</h3>
  535. <p>In Java, multiple class loaders can coexist and
  536. each class loader creates its own name space.
  537. Different class loaders can load different class files with the
  538. same class name. The loaded two classes are regarded as different
  539. ones. This feature enables us to run multiple application programs
  540. on a single JVM even if these programs include different classes
  541. with the same name.
  542. <ul>
  543. <b>Note:</b> The JVM does not allow dynamically reloading a class.
  544. Once a class loader loads a class, it cannot reload a modified
  545. version of that class during runtime. Thus, you cannot alter
  546. the definition of a class after the JVM loads it.
  547. However, the JPDA (Java Platform Debugger Architecture) provides
  548. limited ability for reloading a class.
  549. See <a href="#hotswap">Section 3.6</a>.
  550. </ul>
  551. <p>If the same class file is loaded by two distinct class loaders,
  552. the JVM makes two distinct classes with the same name and definition.
  553. The two classes are regarded as different ones.
  554. Since the two classes are not identical, an instance of one class is
  555. not assignable to a variable of the other class. The cast operation
  556. between the two classes fails
  557. and throws a <em><code>ClassCastException</code></em>.
  558. <p>For example, the following code snippet throws an exception:
  559. <ul><pre>
  560. MyClassLoader myLoader = new MyClassLoader();
  561. Class clazz = myLoader.loadClass("Box");
  562. Object obj = clazz.newInstance();
  563. Box b = (Box)obj; // this always throws ClassCastException.
  564. </pre></ul>
  565. <p>
  566. The <code>Box</code> class is loaded by two class loaders.
  567. Suppose that a class loader CL loads a class including this code snippet.
  568. Since this code snippet refers to <code>MyClassLoader</code>,
  569. <code>Class</code>, <code>Object</code>, and <code>Box</code>,
  570. CL also loads these classes (unless it delegates to another class loader).
  571. Hence the type of the variable <code>b</code> is the <code>Box</code>
  572. class loaded by CL.
  573. On the other hand, <code>myLoader</code> also loads the <code>Box</code>
  574. class. The object <code>obj</code> is an instance of
  575. the <code>Box</code> class loaded by <code>myLoader</code>.
  576. Therefore, the last statement always throws a
  577. <code>ClassCastException</code> since the class of <code>obj</code> is
  578. a different verison of the <code>Box</code> class from one used as the
  579. type of the variable <code>b</code>.
  580. <p>Multiple class loaders form a tree structure.
  581. Each class loader except the bootstrap loader has a
  582. parent class loader, which has normally loaded the class of that child
  583. class loader. Since the request to load a class can be delegated along this
  584. hierarchy of class loaders, a class may be loaded by a class loader that
  585. you do not request the class loading.
  586. Therefore, the class loader that has been requested to load a class C
  587. may be different from the loader that actually loads the class C.
  588. For distinction, we call the former loader <em>the initiator of C</em>
  589. and we call the latter loader <em>the real loader of C</em>.
  590. <p>
  591. Furthermore, if a class loader CL requested to load a class C
  592. (the initiator of C) delegates
  593. to the parent class loader PL, then the class loader CL is never requested
  594. to load any classes referred to in the definition of the class C.
  595. CL is not the initiator of those classes.
  596. Instead, the parent class loader PL becomes their initiators
  597. and it is requested to load them.
  598. <em>The classes that the definition of a class C referes to are loaded by
  599. the real loader of C.</em>
  600. <p>To understand this behavior, let's consider the following example.
  601. <ul><pre>
  602. public class Point { // loaded by PL
  603. private int x, y;
  604. public int getX() { return x; }
  605. :
  606. }
  607. public class Box { // the initiator is L but the real loader is PL
  608. private Point upperLeft, size;
  609. public int getBaseX() { return upperLeft.x; }
  610. :
  611. }
  612. public class Window { // loaded by a class loader L
  613. private Box box;
  614. public int getBaseX() { return box.getBaseX(); }
  615. }</pre></ul>
  616. <p>Suppose that a class <code>Window</code> is loaded by a class loader L.
  617. Both the initiator and the real loader of <code>Window</code> are L.
  618. Since the definition of <code>Window</code> refers to <code>Box</code>,
  619. the JVM will request L to load <code>Box</code>.
  620. Here, suppose that L delegates this task to the parent class loader PL.
  621. The initiator of <code>Box</code> is L but the real loader is PL.
  622. In this case, the initiator of <code>Point</code> is not L but PL
  623. since it is the same as the real loader of <code>Box</code>.
  624. Thus L is never requested to load <code>Point</code>.
  625. <p>Next, let's consider a slightly modified example.
  626. <ul><pre>
  627. public class Point {
  628. private int x, y;
  629. public int getX() { return x; }
  630. :
  631. }
  632. public class Box { // the initiator is L but the real loader is PL
  633. private Point upperLeft, size;
  634. public Point getSize() { return size; }
  635. :
  636. }
  637. public class Window { // loaded by a class loader L
  638. private Box box;
  639. public boolean widthIs(int w) {
  640. Point p = box.getSize();
  641. return w == p.getX();
  642. }
  643. }</pre></ul>
  644. <p>Now, the definition of <code>Window</code> also refers to
  645. <code>Point</code>. In this case, the class loader L must
  646. also delegate to PL if it is requested to load <code>Point</code>.
  647. <em>You must avoid having two class loaders doubly load the same
  648. class.</em> One of the two loaders must delegate to
  649. the other.
  650. <p>
  651. If L does not delegate to PL when <code>Point</code>
  652. is loaded, <code>widthIs()</code> would throw a ClassCastException.
  653. Since the real loader of <code>Box</code> is PL,
  654. <code>Point</code> referred to in <code>Box</code> is also loaded by PL.
  655. Therefore, the resulting value of <code>getSize()</code>
  656. is an instance of <code>Point</code> loaded by PL
  657. whereas the type of the variable <code>p</code> in <code>widthIs()</code>
  658. is <code>Point</code> loaded by L.
  659. The JVM regards them as distinct types and thus it throws an exception
  660. because of type mismatch.
  661. <p>This behavior is somewhat inconvenient but necessary.
  662. If the following statement:
  663. <ul><pre>
  664. Point p = box.getSize();
  665. </pre></ul>
  666. <p>did not throw an exception,
  667. then the programmer of <code>Window</code> could break the encapsulation
  668. of <code>Point</code> objects.
  669. For example, the field <code>x</code>
  670. is private in <code>Point</code> loaded by PL.
  671. However, the <code>Window</code> class could
  672. directly access the value of <code>x</code>
  673. if L loads <code>Point</code> with the following definition:
  674. <ul><pre>
  675. public class Point {
  676. public int x, y; // not private
  677. public int getX() { return x; }
  678. :
  679. }
  680. </pre></ul>
  681. <p>
  682. For more details of class loaders in Java, the following paper would
  683. be helpful:
  684. <ul>Sheng Liang and Gilad Bracha,
  685. "Dynamic Class Loading in the Java Virtual Machine",
  686. <br><i>ACM OOPSLA'98</i>, pp.36-44, 1998.</ul>
  687. <p><br>
  688. <h3>3.3 Using <code>javassist.Loader</code></h3>
  689. <p>Javassist provides a class loader
  690. <code>javassist.Loader</code>. This class loader uses a
  691. <code>javassist.ClassPool</code> object for reading a class file.
  692. <p>For example, <code>javassist.Loader</code> can be used for loading
  693. a particular class modified with Javassist.
  694. <ul><pre>
  695. import javassist.*;
  696. import test.Rectangle;
  697. public class Main {
  698. public static void main(String[] args) throws Throwable {
  699. ClassPool pool = ClassPool.getDefault();
  700. Loader cl = new Loader(pool);
  701. CtClass ct = pool.get("test.Rectangle");
  702. ct.setSuperclass(pool.get("test.Point"));
  703. Class c = cl.loadClass("test.Rectangle");
  704. Object rect = c.newInstance();
  705. :
  706. }
  707. }
  708. </pre></ul>
  709. <p>This program modifies a class <code>test.Rectangle</code>. The
  710. superclass of <code>test.Rectangle</code> is set to a
  711. <code>test.Point</code> class. Then this program loads the modified
  712. class, and creates a new instance of the
  713. <code>test.Rectangle</code> class.
  714. <p>If the users want to modify a class on demand when it is loaded,
  715. the users can add an event listener to a <code>javassist.Loader</code>.
  716. The added event listener is
  717. notified when the class loader loads a class.
  718. The event-listener class must implement the following interface:
  719. <ul><pre>public interface Translator {
  720. public void start(ClassPool pool)
  721. throws NotFoundException, CannotCompileException;
  722. public void onLoad(ClassPool pool, String classname)
  723. throws NotFoundException, CannotCompileException;
  724. }</pre></ul>
  725. <p>The method <code>start()</code> is called when this event listener
  726. is added to a <code>javassist.Loader</code> object by
  727. <code>addTranslator()</code> in <code>javassist.Loader</code>. The
  728. method <code>onLoad()</code> is called before
  729. <code>javassist.Loader</code> loads a class. <code>onLoad()</code>
  730. can modify the definition of the loaded class.
  731. <p>For example, the following event listener changes all classes
  732. to public classes just before they are loaded.
  733. <ul><pre>public class MyTranslator implements Translator {
  734. void start(ClassPool pool)
  735. throws NotFoundException, CannotCompileException {}
  736. void onLoad(ClassPool pool, String classname)
  737. throws NotFoundException, CannotCompileException
  738. {
  739. CtClass cc = pool.get(classname);
  740. cc.setModifiers(Modifier.PUBLIC);
  741. }
  742. }</pre></ul>
  743. <p>Note that <code>onLoad()</code> does not have to call
  744. <code>toBytecode()</code> or <code>writeFile()</code> since
  745. <code>javassist.Loader</code> calls these methods to obtain a class
  746. file.
  747. <p>To run an application class <code>MyApp</code> with a
  748. <code>MyTranslator</code> object, write a main class as following:
  749. <ul><pre>
  750. import javassist.*;
  751. public class Main2 {
  752. public static void main(String[] args) throws Throwable {
  753. Translator t = new MyTranslator();
  754. ClassPool pool = ClassPool.getDefault();
  755. Loader cl = new Loader();
  756. cl.addTranslator(pool, t);
  757. cl.run("MyApp", args);
  758. }
  759. }
  760. </pre></ul>
  761. <p>To run this program, do:
  762. <ul><pre>
  763. % java Main2 <i>arg1</i> <i>arg2</i>...
  764. </pre></ul>
  765. <p>The class <code>MyApp</code> and the other application classes
  766. are translated by <code>MyTranslator</code>.
  767. <p>Note that <em>application</em> classes like <code>MyApp</code> cannot
  768. access the <em>loader</em> classes such as <code>Main2</code>,
  769. <code>MyTranslator</code>, and <code>ClassPool</code> because they
  770. are loaded by different loaders. The application classes are loaded
  771. by <code>javassist.Loader</code> whereas the loader classes such as
  772. <code>Main2</code> are by the default Java class loader.
  773. <p><code>javassist.Loader</code> searches for classes in a different
  774. order from <code>java.lang.ClassLoader</code>.
  775. <code>ClassLoader</code> first delegates the loading operations to
  776. the parent class loader and then attempts to load the classes
  777. only if the parent class loader cannot find them.
  778. On the other hand,
  779. <code>javassist.Loader</code> attempts
  780. to load the classes before delegating to the parent class loader.
  781. It delegates only if:
  782. <ul><li>the classes are not found by calling <code>get()</code> on
  783. a <code>ClassPool</code> object, or
  784. <p><li>the classes have been specified by using
  785. <code>delegateLoadingOf()</code>
  786. to be loaded by the parent class loader.
  787. </ul>
  788. <p>This search order allows loading modified classes by Javassist.
  789. However, it delegates to the parent class loader if it fails
  790. to find modified classes for some reason. Once a class is loaded by
  791. the parent class loader, the other classes referred to in that class will be
  792. also loaded by the parent class loader and thus they are never modified.
  793. Recall that all the classes referred to in a class C are loaded by the
  794. real loader of C.
  795. <em>If your program fails to load a modified class,</em> you should
  796. make sure whether all the classes using that class have been loaded by
  797. <code>javassist.Loader</code>.
  798. <p><br>
  799. <h3>3.4 Writing a class loader</h3>
  800. <p>A simple class loader using Javassist is as follows:
  801. <ul><pre>import javassist.*;
  802. public class SampleLoader extends ClassLoader {
  803. /* Call MyApp.main().
  804. */
  805. public static void main(String[] args) throws Throwable {
  806. SampleLoader s = new SampleLoader();
  807. Class c = s.loadClass("MyApp");
  808. c.getDeclaredMethod("main", new Class[] { String[].class })
  809. .invoke(null, new Object[] { args });
  810. }
  811. private ClassPool pool;
  812. public SampleLoader() throws NotFoundException {
  813. pool = new ClassPool();
  814. pool.insertClassPath("./class"); // <em>MyApp.class must be there.</em>
  815. }
  816. /* Finds a specified class.
  817. * The bytecode for that class can be modified.
  818. */
  819. protected Class findClass(String name) throws ClassNotFoundException {
  820. try {
  821. CtClass cc = pool.get(name);
  822. // <em>modify the CtClass object here</em>
  823. byte[] b = cc.toBytecode();
  824. return defineClass(name, b, 0, b.length);
  825. } catch (NotFoundException e) {
  826. throw new ClassNotFoundException();
  827. } catch (IOException e) {
  828. throw new ClassNotFoundException();
  829. } catch (CannotCompileException e) {
  830. throw new ClassNotFoundException();
  831. }
  832. }
  833. }</pre></ul>
  834. <p>The class <code>MyApp</code> is an application program.
  835. To execute this program, first put the class file under the
  836. <code>./class</code> directory, which must <em>not</em> be included
  837. in the class search path. Otherwise, <code>MyApp.class</code> would
  838. be loaded by the default system class loader, which is the parent
  839. loader of <code>SampleLoader</code>.
  840. The directory name <code>./class</code> is specified by
  841. <code>insertClassPath()</code> in the constructor.
  842. You can choose a different name instead of <code>./class</code> if you want.
  843. Then do as follows:
  844. <ul><code>% java SampleLoader</code></ul>
  845. <p>The class loader loads the class <code>MyApp</code>
  846. (<code>./class/MyApp.class</code>) and calls
  847. <code>MyApp.main()</code> with the command line parameters.
  848. <p>This is the simplest way of using Javassist. However, if you write
  849. a more complex class loader, you may need detailed knowledge of
  850. Java's class loading mechanism. For example, the program above puts the
  851. <code>MyApp</code> class in a name space separated from the name space
  852. that the class <code>SampleLoader</code> belongs to because the two
  853. classes are loaded by different class loaders.
  854. Hence, the
  855. <code>MyApp</code> class cannot directly access the class
  856. <code>SampleLoader</code>.
  857. <p><br>
  858. <h3>3.5 Modifying a system class</h3>
  859. <p>The system classes like <code>java.lang.String</code> cannot be
  860. loaded by a class loader other than the system class loader.
  861. Therefore, <code>SampleLoader</code> or <code>javassist.Loader</code>
  862. shown above cannot modify the system classes at loading time.
  863. <p>If your application needs to do that, the system classes must be
  864. <em>statically</em> modified. For example, the following program
  865. adds a new field <code>hiddenValue</code> to <code>java.lang.String</code>:
  866. <ul><pre>ClassPool pool = ClassPool.getDefault();
  867. CtClass cc = pool.get("java.lang.String");
  868. CtField f = new CtField(CtClass.intType, "hiddenValue", cc);
  869. f.setModifiers(Modifier.PUBLIC);
  870. cc.addField(f);
  871. cc.writeFile(".");</pre></ul>
  872. <p>This program produces a file <code>"./java/lang/String.class"</code>.
  873. <p>To run your program <code>MyApp</code>
  874. with this modified <code>String</code> class, do as follows:
  875. <ul><pre>
  876. % java -Xbootclasspath/p:. MyApp <i>arg1</i> <i>arg2</i>...
  877. </pre></ul>
  878. <p>Suppose that the definition of <code>MyApp</code> is as follows:
  879. <ul><pre>public class MyApp {
  880. public static void main(String[] args) throws Exception {
  881. System.out.println(String.class.getField("hiddenValue").getName());
  882. }
  883. }</pre></ul>
  884. <p>If the modified <code>String</code> class is correctly loaded,
  885. <code>MyApp</code> prints <code>hiddenValue</code>.
  886. <p><i>Note: Applications that use this technique for the purpose of
  887. overriding a system class in <code>rt.jar</code> should not be
  888. deployed as doing so would contravene the Java 2 Runtime Environment
  889. binary code license.</i>
  890. <p><br>
  891. <a name="hotswap">
  892. <h3>3.6 Reloading a class at runtime</h3></a>
  893. <p>If the JVM is launched with the JPDA (Java Platform Debugger
  894. Architecture) enabled, a class is dynamically reloadable. After the
  895. JVM loads a class, the old version of the class definition can be
  896. unloaded and a new one can be reloaded again. That is, the definition
  897. of that class can be dynamically modified during runtime. However,
  898. the new class definition must be somewhat compatible to the old one.
  899. <em>The JVM does not allow schema changes between the two versions.</em>
  900. They have the same set of methods and fields.
  901. <p>Javassist provides a convenient class for reloading a class at runtime.
  902. For more information, see the API documentation of
  903. <code>javassist.tools.HotSwapper</code>.
  904. <p><br>
  905. <a href="tutorial2.html">Next page</a>
  906. <hr>
  907. Java(TM) is a trademark of Sun Microsystems, Inc.<br>
  908. Copyright (C) 2000-2012 by Shigeru Chiba, All rights reserved.
  909. </body>
  910. </html>