-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
267 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,4 +7,5 @@ Java™ Platform Standard Ed. 8 | |
:numbered: 0 | ||
|
||
jdkJre | ||
Lambda | ||
Lambda | ||
javassistTutorial |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
# Javassist Tutorial | ||
|
||
## 1. Reading and writing bytecode | ||
The class `Javassist.CtClass` is an abstract representation of a class file. A `CtClass` (compile-time class) object is a handle for dealing with a class file. | ||
``` | ||
ClassPool pool = ClassPool.getDefault(); | ||
CtClass cc = pool.get("test.Rectangle"); | ||
cc.setSuperclass(pool.get("test.Point")); | ||
cc.writeFile(); | ||
``` | ||
|
||
### Defining a new class | ||
To define a new class from scratch, `makeClass()` must be called on a `ClassPool`. | ||
``` | ||
ClassPool pool = ClassPool.getDefault(); | ||
CtClass cc = pool.makeClass("Point"); | ||
``` | ||
|
||
### Frozen classes | ||
If a `CtClass` object is converted into a class file by `writeFile()`, `toClass()`, or `toBytecode()`, Javassist freezes that `CtClass` object. Further modifications of that `CtClass` object are not permitted. This is for warning the developers when they attempt to modify a class file that has been already loaded since the JVM does not allow reloading a class. | ||
|
||
To disallow pruning a particular `CtClass`, `stopPruning()` must be called on that object in advance | ||
|
||
### Class search path | ||
``` | ||
ClassPool pool = ClassPool.getDefault(); | ||
pool.insertClassPath("/usr/local/javalib"); | ||
``` | ||
|
||
## 2. ClassPool | ||
A `ClassPool` object is a container of `CtClass` objects. Once a `CtClass` object is created, it is recorded in a `ClassPool` for ever. This is because a compiler may need to access the `CtClass` object later when it compiles source code that refers to the class represented by that `CtClass`. | ||
|
||
### Avoid out of memory | ||
``` | ||
CtClass cc = ... ; | ||
cc.writeFile(); | ||
cc.detach(); | ||
``` | ||
``` | ||
ClassPool cp = new ClassPool(true); | ||
// if needed, append an extra search path by appendClassPath() | ||
ClassPool cp = new ClassPool(); | ||
cp.appendSystemPath(); // or append another path by appendClassPath() | ||
``` | ||
|
||
### Cascaded ClassPools | ||
Multiple `ClassPool` objects can be cascaded like `java.lang.ClassLoader`. | ||
``` | ||
ClassPool parent = ClassPool.getDefault(); | ||
ClassPool child = new ClassPool(parent); | ||
child.insertClassPath("./classes"); | ||
``` | ||
``` | ||
ClassPool parent = ClassPool.getDefault(); | ||
ClassPool child = new ClassPool(parent); | ||
child.appendSystemPath(); // the same class path as the default one. | ||
child.childFirstLookup = true; // changes the behavior of the child. | ||
``` | ||
|
||
### Changing a class name for defining a new class | ||
``` | ||
ClassPool pool = ClassPool.getDefault(); | ||
CtClass cc = pool.get("Point"); | ||
cc.setName("Pair"); | ||
``` | ||
``` | ||
ClassPool pool = ClassPool.getDefault(); | ||
CtClass cc = pool.get("Point"); | ||
CtClass cc1 = pool.get("Point"); // cc1 is identical to cc. | ||
cc.setName("Pair"); | ||
CtClass cc2 = pool.get("Pair"); // cc2 is identical to cc. | ||
CtClass cc3 = pool.get("Point"); // cc3 is not identical to cc. | ||
``` | ||
|
||
### Renaming a frozen class for defining a new class | ||
Once a `CtClass` object is converted into a class file by `writeFile()` or `toBytecode()`, Javassist rejects further modifications of that `CtClass` object. | ||
``` | ||
ClassPool pool = ClassPool.getDefault(); | ||
CtClass cc = pool.get("Point"); | ||
cc.writeFile(); | ||
CtClass cc2 = pool.getAndRename("Point", "Pair"); | ||
``` | ||
If `getAndRename()` is called, the `ClassPool` first reads `Point.class` for creating a new `CtClass` object representing `Point` class. However, it renames that `CtClass` object from `Point` to `Pair` before it records that `CtClass` object in a hash table. Thus `getAndRename()` can be executed after `writeFile()` or `toBytecode()` is called on the the `CtClass` object representing `Point` class. | ||
|
||
## 3. Class loader | ||
1. Get a `CtClass` object by calling `ClassPool.get()`, | ||
2. Modify it, and | ||
3. Call `writeFile()` or `toBytecode()` on that `CtClass` object to obtain a modified class file. | ||
|
||
### 3.1 The toClass method in CtClass | ||
|
||
|
||
### 3.2 Class loading in Java | ||
|
||
|
||
### 3.3 Using javassist.Loader | ||
|
||
|
||
### 3.4 Writing a class loader | ||
|
||
|
||
### 3.5 Modifying a system class | ||
|
||
|
||
### 3.6 Reloading a class at runtime | ||
|
||
|
||
## 4. Introspection and customization | ||
|
||
|
||
|
||
## 5. Bytecode level API | ||
|
||
|
||
|
||
## 6. Generics | ||
|
||
|
||
|
||
## 7. Varargs | ||
|
||
|
||
|
||
## 8. J2ME | ||
|
||
|
||
|
||
## 9. Boxing/Unboxing | ||
|
||
|
||
|
||
## 10. Debug | ||
|
||
|
||
## References | ||
- [Getting Started with Javassist](http://www.javassist.org/tutorial/tutorial.html) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package t5750.javassist; | ||
|
||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import javassist.ClassPool; | ||
import javassist.CtClass; | ||
import t5750.javassist.util.JavassistUtil; | ||
|
||
public class ClassPoolTest { | ||
private ClassPool pool; | ||
|
||
@Before | ||
public void setup() { | ||
pool = ClassPool.getDefault(); | ||
} | ||
|
||
@Test | ||
public void main() throws Exception { | ||
CtClass cc = pool.get(JavassistUtil.DOMAIN + "Rectangle"); | ||
cc.setSuperclass(pool.get(JavassistUtil.POINT)); | ||
cc.writeFile(); | ||
// Avoid out of memory | ||
cc.detach(); | ||
// Cascaded ClassPools | ||
ClassPool child = new ClassPool(pool); | ||
child.insertClassPath("./classes"); | ||
// Changing a class name for defining a new class | ||
cc = pool.get(JavassistUtil.POINT); | ||
CtClass cc1 = pool.get(JavassistUtil.POINT); // cc1 is identical to cc. | ||
cc.setName(JavassistUtil.DOMAIN + "Pair"); | ||
// cc2 is identical to cc. | ||
CtClass cc2 = pool.get(JavassistUtil.DOMAIN + "Pair"); | ||
// cc3 is not identical to cc. | ||
CtClass cc3 = pool.get(JavassistUtil.POINT); | ||
cc.writeFile(); | ||
System.out.println("cc cc1: " + cc.equals(cc1)); | ||
System.out.println("cc cc2: " + cc.equals(cc2)); | ||
System.out.println("cc2 cc3: " + cc2.equals(cc3)); | ||
// Renaming a frozen class for defining a new class | ||
// cc.setName("Pair"); // wrong since writeFile() has been called. | ||
CtClass ccPointPair = pool.getAndRename(JavassistUtil.POINT, | ||
JavassistUtil.DOMAIN + "PointPair"); | ||
ccPointPair.writeFile(); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
jdk8/src/test/java/t5750/javassist/ReadWriteBytecodeTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package t5750.javassist; | ||
|
||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import javassist.ClassPath; | ||
import javassist.ClassPool; | ||
import javassist.CtClass; | ||
import javassist.URLClassPath; | ||
import t5750.javassist.util.JavassistUtil; | ||
|
||
public class ReadWriteBytecodeTest { | ||
private ClassPool pool; | ||
private ClassPool poolNew; | ||
|
||
@Before | ||
public void setup() { | ||
pool = ClassPool.getDefault(); | ||
poolNew = ClassPool.getDefault(); | ||
} | ||
|
||
@Test | ||
public void main() throws Exception { | ||
CtClass cc = pool.get(JavassistUtil.DOMAIN + "Rectangle"); | ||
cc.setSuperclass(pool.get("java.awt.Point")); | ||
cc.writeFile(); | ||
byte[] b = cc.toBytecode(); | ||
Class clazz = cc.toClass(); | ||
System.out.println(clazz.getSuperclass()); | ||
// Defining a new class | ||
CtClass ccNew = poolNew.makeClass(JavassistUtil.DOMAIN + "Point"); | ||
ccNew.writeFile(); | ||
// Frozen classes | ||
ccNew.defrost(); | ||
ccNew.setSuperclass(poolNew.get("java.awt.geom.Point2D")); | ||
ccNew.stopPruning(true); | ||
ccNew.writeFile(); | ||
} | ||
|
||
@Test | ||
public void classSearchPath() throws Exception { | ||
// Class search path | ||
// http://localhost:8000/test2/IncOp.class | ||
ClassPath cp = new URLClassPath("localhost", 8000, "/", null); | ||
poolNew.insertClassPath(cp); | ||
CtClass ccPath = poolNew | ||
.makeClass(JavassistUtil.DOMAIN + "ClassSearchPath"); | ||
ccPath.setSuperclass(poolNew.get("test2.IncOp")); | ||
ccPath.writeFile(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package t5750.javassist.domain; | ||
|
||
public class Rectangle { | ||
private int width; | ||
private int height; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package t5750.javassist.util; | ||
|
||
public final class JavassistUtil { | ||
public static final String DOMAIN = "t5750.javassist.domain."; | ||
public static final String POINT = "java.awt.Point"; | ||
} |