aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Readme.html3
-rw-r--r--tutorial/tutorial.html151
2 files changed, 104 insertions, 50 deletions
diff --git a/Readme.html b/Readme.html
index 8ce4d36a..59b76998 100644
--- a/Readme.html
+++ b/Readme.html
@@ -555,7 +555,8 @@ Remy Sanlaville, Muga Nishizawa, Alexey Loubyansky, Saori Oki,
Andreas Salathe, Dante Torres estrada, S. Pam, Nuno Santos,
Denis Taye, Colin Sampaleanu, Robert Bialek, Asato Shimotaki,
Howard Lewis Ship, Richard Jones, Marjan Sterjev,
-Bruce McDonald, Mark Brennan, and Vlad Skarzhevskyy.
+Bruce McDonald, Mark Brennan, Vlad Skarzhevskyy,
+and Brett Randall
for their contributions.
<p><br>
diff --git a/tutorial/tutorial.html b/tutorial/tutorial.html
index 6c9df81d..0598f60b 100644
--- a/tutorial/tutorial.html
+++ b/tutorial/tutorial.html
@@ -45,50 +45,38 @@ following program is a very simple example:
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("test.Rectangle");
cc.setSuperclass(pool.get("test.Point"));
-cc.writeFile("test.Rectangle");
+cc.writeFile();
</pre></ul>
-<p>This program first obtains a <code>ClassPool</code> object,
-which controls bytecode modification with Javassist.
-The <code>ClassPool</code> object is a container of <code>CtClass</code>
-object representing a class file.
-It reads a class file on demand for constructing a <code>CtClass</code>
-object and contains the constructed object until it is written out
-to a file or an output stream.
-
-<p>The <code>ClassPool</code> object is used to maintain one-to-one
-mapping between classes and <code>CtClass</code> objects. Javassist
-never allows two distinct <code>CtClass</code> objects to represent
-the same class unless two independent <code>ClassPool</code> are created.
-This is a significant feature for consistent program
-transformation. To create multiple
-instances of <code>ClassPool</code>, write the following code:
-
-<ul><pre>
-ClassPool cp = new ClassPool();
-cp.appendSystemPath(); // or append another path by appendClassPath()
-</pre></ul>
+<p>This program first obtains a <code>ClassPool</code> object, which
+controls bytecode modification with Javassist. The
+<code>ClassPool</code> object is a container of <code>CtClass</code>
+object representing a class file. It reads a class file on demand for
+constructing a <code>CtClass</code> object and records the
+constructed object for responding later accesses.
-<p>This creates a <code>ClassPool</code> object that behaves as the
-default <code>ClassPool</code> returned by
-<code>ClassPool.getDefault()</code> does.
-<code>ClassPool.getDefault()</code> is a singleton factory method
-provided for convenience.
-
-<p>If you have two <code>ClassPool</code> objects, then you can
-obtain, from each <code>ClassPool</code>, a distinct
-<code>CtClass</code> object representing the same class file. You can
-differently modify these <code>CtClass</code> objects to generate
-different versions of the class.
-
-<p>To modify the definition of a class, the users must first obtain a
-reference to the <code>CtClass</code> object representing that class.
+To modify the definition of a class, the users must first obtain
+from a <code>ClassPool</code> object
+a reference to a <code>CtClass</code> object representing that class.
<code>get()</code> in <code>ClassPool</code> is used for this purpose.
-In the case of the program shown at the beginning, the
+In the case of the program shown above, the
<code>CtClass</code> object representing a class
<code>test.Rectangle</code> is obtained from the
<code>ClassPool</code> object and it is assigned to a variable
-<code>cc</code>. Then it is modified so that the superclass of
+<code>cc</code>.
+
+<p>From the implementation viewpoint, <code>ClassPool</code> is a hash
+table of <code>CtClass</code> objects, which uses the class names as
+keys. <code>get()</code> in <code>ClassPool</code> searches this hash
+table to find a <code>CtClass</code> object associated with the
+specified key. If such a <code>CtClass</code> object is not found,
+<code>get()</code> reads a class file to construct a new
+<code>CtClass</code> object, which is recorded in the hash table and
+then returned as the resulting value of <code>get()</code>.
+
+<p>The <code>CtClass</code> object obtained from a <code>ClassPool</code>
+object can be modified.
+In the example above, it is modified so that the superclass of
<code>test.Rectangle</code> is changed into a class
<code>test.Point</code>. This change is reflected on the original
class file when <code>writeFile()</code> in <code>CtClass()</code> is
@@ -103,6 +91,8 @@ modified bytecode. To obtain the bytecode, call <code>toBytecode()</code>:
byte[] b = cc.toBytecode();
</pre></ul>
+<h4>Class search path</h4>
+
<p>The default <code>ClassPool</code> returned
by a static method <code>ClassPool.getDefault()</code>
searches the same path that the underlying JVM (Java virtual machine) has.
@@ -124,7 +114,6 @@ You can use any <code>Class</code> object as an argument instead of
<code>this.getClass()</code>. The class path used for loading the
class represented by that <code>Class</code> object is registered.
-
<p>
You can register a directory name as the class search path.
For example, the following code adds a directory
@@ -221,13 +210,32 @@ CtClass cc = pool.get("Point");
cc.setName("Pair");
</pre></ul>
-<p>This program first obtains the <code>CtClass</code> object
-for class <code>Point</code>. Then it gives a new name <code>Pair</code>
-to that <code>CtClass</code> object.
-If <code>get("Point")</code> is later called on the <code>ClassPool</code>
-object again, then a class file <code>Point.class</code> is read again and
-a new <code>CtClass</code> object for class <code>Point</code> is constructed
-again. See the followings:
+<p>This program first obtains the <code>CtClass</code> object for
+class <code>Point</code>. Then it calls <code>setName()</code> to
+give a new name <code>Pair</code> to that <code>CtClass</code> object.
+After this call, all occurrences of the class name in the class
+definition represented by that <code>CtClass</code> object are changed
+from <code>Point</code> to <code>Pair</code>. The other part of the
+class definition does not change.
+
+<p>Note that <code>setName()</code> in <code>CtClass</code> changes a
+record in the <code>ClassPool</code> object. From the implementation
+viewpoint, a <code>ClassPool</code> object is a hash table of
+<code>CtClass</code> objects. <code>setName()</code> changes
+the key associated to the <code>CtClass</code> object in the hash
+table. The key is changed from the original class name to the new
+class name.
+
+<p>Therefore, if <code>get("Point")</code> is later called on the
+<code>ClassPool</code> object again, then it never returns the
+<code>CtClass</code> object that the variable <code>cc</code> refers to.
+The <code>ClassPool</code> object reads
+a class file
+<code>Point.class</code> again and it constructs a new <code>CtClass</code>
+object for class <code>Point</code>.
+This is because the <code>CtClass</code> object associated with the name
+<code>Point</code> does not exist any more.
+See the followings:
<ul><pre>
ClassPool pool = ClassPool.getDefault();
@@ -238,6 +246,38 @@ CtClass cc2 = pool.get("Pair"); // cc2 is identical to cc.
CtClass cc3 = pool.get("Point"); // cc3 is not identical to cc.
</pre></ul>
+<p><code>cc1</code> and <code>cc2</code> refer to the same instance of
+<code>CtClass</code> that <code>cc</code> does whereas
+<code>cc3</code> does not. Note that, after
+<code>cc.setName("Pair")</code> is executed, the <code>CtClass</code>
+object that <code>cc</code> and <code>cc1</code> refer to represents
+the <code>Pair</code> class.
+
+<p>The <code>ClassPool</code> object is used to maintain one-to-one
+mapping between classes and <code>CtClass</code> objects. Javassist
+never allows two distinct <code>CtClass</code> objects to represent
+the same class unless two independent <code>ClassPool</code> are created.
+This is a significant feature for consistent program
+transformation. To create multiple
+instances of <code>ClassPool</code>, write the following code:
+
+<ul><pre>
+ClassPool cp = new ClassPool();
+cp.appendSystemPath(); // or append another path by appendClassPath()
+</pre></ul>
+
+<p>This creates a <code>ClassPool</code> object that behaves as the
+default <code>ClassPool</code> returned by
+<code>ClassPool.getDefault()</code> does.
+<code>ClassPool.getDefault()</code> is a singleton factory method
+provided for convenience.
+
+<p>If you have two <code>ClassPool</code> objects, then you can
+obtain, from each <code>ClassPool</code>, a distinct
+<code>CtClass</code> object representing the same class file. You can
+differently modify these <code>CtClass</code> objects to generate
+different versions of the class.
+
<p>Once a <code>CtClass</code> object is converted into a class file
by <code>writeFile()</code> or <code>toBytecode()</code>, Javassist
rejects further modifications of that <code>CtClass</code> object.
@@ -245,20 +285,33 @@ Hence, after the <code>CtClass</code> object representing <code>Point</code>
class is converted into a class file, you cannot define <code>Pair</code>
class as a copy of <code>Point</code> since executing <code>setName()</code>
on <code>Point</code> is rejected.
+The following code snippet is wrong:
+
+<ul><pre>
+ClassPool pool = ClassPool.getDefault();
+CtClass cc = pool.get("Point");
+cc.writeFile();
+cc.setName("Pair"); // wrong since writeFile() has been called.
+</pre></ul>
<p>To avoid this restriction, you should call <code>getAndRename()</code>
in <code>ClassPool</code>. For example,
<ul><pre>
ClassPool pool = ClassPool.getDefault();
-CtClass cc = pool.getAndRename("Point", "Pair");
+CtClass cc = pool.get("Point");
+cc.writeFile();
+CtClass cc2 = pool.getAndRename("Point", "Pair");
</pre></ul>
<p>If <code>getAndRename()</code> is called, the <code>ClassPool</code>
-reads <code>Point.class</code> for creating a new <code>CtClass</code>
-object representing <code>Pair</code> class. <code>getAndRename()</code>
+first reads <code>Point.class</code> for creating a new <code>CtClass</code>
+object representing <code>Point</code> class. However, it renames that
+<code>CtClass</code> object from <code>Point</code> to <code>Pair</code> before
+it records that <code>CtClass</code> object in a hash table.
+Thus <code>getAndRename()</code>
can be executed after <code>writeFile()</code> or <code>toBytecode()</code>
-is called on the the <code>ClassPool</code> representing <code>Point</code>
+is called on the the <code>CtClass</code> object representing <code>Point</code>
class.