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