Browse Source

update javadoc comments.


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@70 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 20 years ago
parent
commit
0cbf7a9b80
2 changed files with 166 additions and 94 deletions
  1. 20
    1
      src/main/javassist/ClassPool.java
  2. 146
    93
      tutorial/tutorial.html

+ 20
- 1
src/main/javassist/ClassPool.java View File

@@ -70,6 +70,17 @@ import java.util.Hashtable;
*
* <p>The implementation of this class is thread-safe.
*
* <p><b>Memory consumption memo:</b>
*
* <p><code>ClassPool</code> objects hold all the <code>CtClass</code>es
* that have been created so that the consistency among modified classes
* can be guaranteed. Thus if a large number of <code>CtClass</code>es
* are processed, the <code>ClassPool</code> will consume a huge amount
* of memory. To avoid this, multiple <code>ClassPool</code> objects
* must be used. Note that <code>getDefault()</code> is a singleton
* factory.
*
*
* @see javassist.CtClass
* @see javassist.ClassPath
* @see javassist.Translator
@@ -159,7 +170,8 @@ public class ClassPool {

/**
* Returns the default class pool.
* The returned object is always identical.
* The returned object is always identical since this method is
* a singleton factory.
*
* <p>The default class pool searches the system search path,
* which usually includes the platform library, extension
@@ -167,6 +179,13 @@ public class ClassPool {
* <code>-classpath</code> option or the <code>CLASSPATH</code>
* environment variable.
*
* <p>When this method is called for the first time, the default
* class pool is created with the following code snippet:
*
* <ul><code>ClassPool cp = new ClassPool(null);
* cp.appendSystemPath();
* </code></ul>
*
* @param t null or the translator linked to the class pool.
*/
public static synchronized ClassPool getDefault(Translator t) {

+ 146
- 93
tutorial/tutorial.html View File

@@ -336,29 +336,153 @@ by a single class loader. You should
avoid loading part of the application program with the default class loader
and the rest of the program with a user-defined class loader.

<p>In Java, multiple class loaders can coexist in Java and they form a
tree structure. Each class loader except the bootstrap loader has a
parent class loader, which normally loaded the class of that child
class loader. Since the request to load a class can be delegated along this
hierarchy of class loaders, a class may be loaded by a class loader that
you do not request the class loading.
<p><br>

Furthermore, if a class loader CL requested to load a class C delegates
to the parenet class loader, then the class loader CL is never requested
to load any classes included in the definition of the class C.
Instead, the parent class loader of CL is requested to load them.
<h3>4.1 Class loading in Java</h3>

<p>Different class loaders can load different class files with the
<p>In Java, multiple class loaders can coexist and
each class loader creates its own name space.
Different class loaders can load different class files with the
same class name. The loaded two classes are regarded as different
ones. If the same class file is loaded by two distinct class loaders,
ones. This feature enables us to run multiple application programs
on a single JVM.

<p>If the same class file is loaded by two distinct class loaders,
the JVM makes two distinct classes with the same name and definition.
The two classes are regarded as different ones.
Since the two classes are not identical, an instance of one class is
not assignable to a variable of the other class. The cast operation
between the two classes fails and throws a <code>ClassCastException</code>.

<p>Multiple class loaders form a tree structure.
Each class loader except the bootstrap loader has a
parent class loader, which has normally loaded the class of that child
class loader. Since the request to load a class can be delegated along this
hierarchy of class loaders, a class may be loaded by a class loader that
you do not request the class loading.
Therefore, the class loader that has been requested to load a class C
may be different from the loader that actually loads the class C.
For distinction, we call the former loader <em>the initiator of C</em>
and we call the latter loader <em>the real loader of C</em>.

<p>
Furthermore, if a class loader CL requested to load a class C
(the initiator of C) delegates
to the parent class loader PL, then the class loader CL is never requested
to load any classes referred to in the definition of the class C.
CL is not the initiator of those classes.
Instead, the parent class loader PL becomes their initiators
and it is requested to load them.
<em>The classes that the definition of a class C referes to are loaded by
the real loader of C.</em>

<p>To understand this behavior, let's consider the following example.

<ul><pre>
public class Point { // loaded by PL
private int x, y;
public int getX() { return x; }
:
}

public class Box { // the initiator is L but the real loader is PL
private Point upperLeft, size;
public int getBaseX() { return upperLeft.x; }
:
}

public class Window { // loaded by a class loader L
private Box box;
public int getBaseX() { return box.getBaseX(); }
}</pre></ul>

<p>Suppose that a class <code>Window</code> is loaded by a class loader L.
Both the initiator and the real loader of <code>Window</code> are L.
Since the definition of <code>Window</code> refers to <code>Box</code>,
the JVM will request L to load <code>Box</code>.
Here, suppose that L delegates this task to the parent class loader PL.
The initiator of <code>Box</code> is L but the real loader is PL.
In this case, the initiator of <code>Point</code> is not L but PL
since it is the same as the real loader of <code>Box</code>.
Thus L is never requested to load <code>Point</code>.

<p>Next, let's consider a slightly modified example.

<ul><pre>
public class Point {
private int x, y;
public int getX() { return x; }
:
}

public class Box { // the initiator is L but the real loader is PL
private Point upperLeft, size;
public Point getSize() { return size; }
:
}

public class Window { // loaded by a class loader L
private Box box;
public boolean widthIs(int w) {
Point p = box.getSize();
return w == p.getX();
}
}</pre></ul>

<p>Now, the definition of <code>Window</code> also refers to
<code>Point</code>. In this case, the class loader L must
also delegate to PL if it is requested to load <code>Point</code>.
<em>You must avoid having two class loaders doubly load the same
class.</em> One of the two loaders must delegate to
the other.

<p>
If L does not delegate to PL when <code>Point</code>
is loaded, <code>widthIs()</code> would throw a ClassCastException.
Since the real loader of <code>Box</code> is PL,
<code>Point</code> referred to in <code>Box</code> is also loaded by PL.
Therefore, the resulting value of <code>getSize()</code>
is an instance of <code>Point</code> loaded by PL
whereas the type of the variable <code>p</code> in <code>widthIs()</code>
is <code>Point</code> loaded by L.
The JVM regards them as distinct types and thus it throws an exception
because of type mismatch.

<p>This behavior is somewhat inconvenient but necessary.
If the following statement:

<ul><pre>
Point p = box.getSize();
</pre></ul>

<p>did not throw an exception,
then the programmer of <code>Window</code> could break the encapsulation
of <code>Point</code> objects.
For example, the field <code>x</code>
is private in <code>Point</code> loaded by PL.
However, the <code>Window</code> class could
directly access the value of <code>x</code>
if L loads <code>Point</code> with the following definition:

<ul><pre>
public class Point {
public int x, y; // not private
public int getX() { return x; }
:
}
</pre></ul>

<p>
For more details of class loaders in Java, the following paper would
be helpful:

<ul>Sheng Liang and Gilad Bracha,
"Dynamic Class Loading in the Java Virtual Machine",
<br><i>ACM OOPSLA'98</i>, pp.36-44, 1998.</ul>

<p><br>

<h3>4.1 Using <code>javassist.Loader</code></h3>
<h3>4.2 Using <code>javassist.Loader</code></h3>

<p>Javassist provides a class loader
<code>javassist.Loader</code>. This class loader uses a
@@ -429,78 +553,6 @@ are loaded by different loaders. The application classes are loaded
by <code>javassist.Loader</code> whereas the loader classes such as
<code>Main</code> are by the default Java class loader.

<p>In Java, for security reasons, the same class file may be loaded
by two distinct class loaders so that two different
classes would be created. For example,

<ul><pre>class Point {
int x, y;
}

class Box {
Point base;
Point getBase() { return base; }
}

class Window {
Point size;
Point getSize() { return size; }
}</pre></ul>

<p>Suppose that a class <code>Box</code> is loaded by a class loader
<code>L1</code> while a class <code>Window</code> is loaded by a class
loader <code>L2</code>. Then, the obejcts returned by
<code>getBase()</code> and <code>getSize()</code> are not instances of
the same class <code>Point</code>.
<code>getBase()</code> returns an instance of the class <code>Point</code>
loaded by <code>L1</code> whereas <code>getSize()</code> returns an
instance of <code>Point</code> loaded by <code>L2</code>. The two versions
of the class <code>Point</code> are distinct. They belong to different
name spaces. For more details, see the following paper:

<ul>Sheng Liang and Gilad Bracha,
"Dynamic Class Loading in the Java Virtual Machine",
<br><i>ACM OOPSLA'98</i>, pp.36-44, 1998.</ul>

<p>To avoid this problem, the two class loaders <code>L1</code> and
<code>L2</code> must delegate the loading operation of the class
<code>Point</code> to another class loader, <code>L3</code>, which is
a parent class loader of <code>L1</code> and <code>L2</code>.
<code>delegateLoadingOf()</code> in <code>javassist.Loader</code>
is a method for specifying what classes should be loaded by the
parent loader.

<p>If <code>L1</code> is the parent class loader of <code>L2</code>,
that is, if <code>L1</code> loads the class of <code>L2</code>,
then <code>L2</code> can delegate the loading operation of
<code>Point</code> to <code>L1</code> for avoiding the problem above.
However, this technique does not work in the case below:

<ul><pre>class Point { // loaded by L1
Window win;
int x, y;
}

class Box { // loaded by L1
Point base;
Point getBase() { return base; }
}

class Window { // loaded by L2
Point size;
Point getSize() { size.win = this; return size; }
}</pre></ul>

<p>Since all the classes included in a class definition loaded by
a class loader <code>L1</code> are also loaded by <code>L1</code>,
the class of the field <code>win</code> in <code>Point</code> is
now the class <code>Window</code> loaded by <code>L1</code>.
Thus <code>size.win = this</code> in <code>getSize()</code> throws
a <code>ClassCastException</code> because of type mismatch; the type of
<code>size.win</code> is the class <code>Point</code> loaded by
<code>L1</code> whereas the type of <code>this</code> is the class
<code>Point</code> loaded by <code>L2</code>.

<p><code>javassist.Loader</code> searches for classes in a different
order from <code>java.lang.ClassLoader</code>.
<code>ClassLoader</code> first delegates the loading operations to
@@ -522,15 +574,17 @@ to be loaded by the parent class loader.
<p>This search order allows loading modified classes by Javassist into
the JVM. However, it delegates to the parent class loader if it fails
to find modified classes for some reason. Once a class is loaded by
the parent class loader, the other classes used by that class will be
also loaded without modification by the parent class loader. <em>If your
program fails to load a modified class,</em> you should make sure whether
all the classes using that class have been loaded by
the parent class loader, the other classes referred to in that class will be
also loaded without modification by the parent class loader.
Recall that all the classes referred to in a class C are loaded by the
real loader of C.
<em>If your program fails to load a modified class,</em> you should
make sure whether all the classes using that class have been loaded by
<code>javassist.Loader</code>.

<p><br>

<h3>4.2 Writing a class loader</h3>
<h3>4.3 Writing a class loader</h3>

<p>A simple class loader using Javassist is as follows:

@@ -602,7 +656,7 @@ Hence, the

<p><br>

<h3>4.3 The <code>toClass</code> method in <code>CtClass</code></h3>
<h3>4.4 The <code>toClass</code> method in <code>CtClass</code></h3>

<p>The <code>CtClass</code> provides a convenience method
<code>toClass</code>, which loads the class by an internal class
@@ -640,10 +694,9 @@ loaded by <code>loadClass()</code>. If you encounter an unexpected
of the class by calling <code>getClassLoader()</code>
in <code>java.lang.Class</code>.


<p><br>

<h3>4.4 Modifying a system class</h3>
<h3>4.5 Modifying a system class</h3>

<p>The system classes like <code>java.lang.String</code> cannot be
loaded by a class loader other than the system class loader.

Loading…
Cancel
Save