diff options
Diffstat (limited to 'sample/evolve/Evolution.java')
-rw-r--r-- | sample/evolve/Evolution.java | 309 |
1 files changed, 148 insertions, 161 deletions
diff --git a/sample/evolve/Evolution.java b/sample/evolve/Evolution.java index 110e9332..ecae0921 100644 --- a/sample/evolve/Evolution.java +++ b/sample/evolve/Evolution.java @@ -1,202 +1,189 @@ package sample.evolve;
import javassist.*;
-import java.io.IOException;
/**
* Evolution provides a set of methods for instrumenting bytecodes.
- *
- * For class evolution, updatable class A is renamed to B. Then an
- * abstract class named A is produced as the super class of B. If the
- * original class A has a public method m(), then the abstract class A
- * has an abstract method m().
- *
- * abstract class A
- * abstract m()
- * _makeInstance()
- * |
- * class A --------> class B
- * m() m()
- *
- * Also, all the other classes are translated so that "new A(i)"
- * in the methods is replaced with "_makeInstance(i)". This makes
- * it possible to change the behavior of the instantiation of
- * the class A.
+ *
+ * For class evolution, updatable class A is renamed to B. Then an abstract
+ * class named A is produced as the super class of B. If the original class A
+ * has a public method m(), then the abstract class A has an abstract method
+ * m().
+ *
+ * abstract class A abstract m() _makeInstance() | class A --------> class B m()
+ * m()
+ *
+ * Also, all the other classes are translated so that "new A(i)" in the methods
+ * is replaced with "_makeInstance(i)". This makes it possible to change the
+ * behavior of the instantiation of the class A.
*/
public class Evolution implements Translator {
public final static String handlerMethod = "_makeInstance";
- public final static String latestVersionField
- = VersionManager.latestVersionField;
+
+ public final static String latestVersionField = VersionManager.latestVersionField;
+
public final static String versionManagerMethod = "initialVersion";
private static CtMethod trapMethod;
+
private static final int initialVersion = 0;
+
private ClassPool pool;
+
private String updatableClassName = null;
+
private CtClass updatableClass = null;
public void start(ClassPool _pool) throws NotFoundException {
- pool = _pool;
+ pool = _pool;
- // Get the definition of Sample.make() and store it into trapMethod
- // for later use.
- trapMethod = _pool.getMethod("sample.evolve.Sample", "make");
+ // Get the definition of Sample.make() and store it into trapMethod
+ // for later use.
+ trapMethod = _pool.getMethod("sample.evolve.Sample", "make");
}
public void onLoad(ClassPool _pool, String classname)
- throws NotFoundException, CannotCompileException
- {
- onLoadUpdatable(classname);
-
- /*
- * Replaces all the occurrences of the new operator with a call
- * to _makeInstance().
- */
- CtClass clazz = _pool.get(classname);
- CtClass absClass = updatableClass;
- CodeConverter converter = new CodeConverter();
- converter.replaceNew(absClass, absClass, handlerMethod);
- clazz.instrument(converter);
+ throws NotFoundException, CannotCompileException {
+ onLoadUpdatable(classname);
+
+ /*
+ * Replaces all the occurrences of the new operator with a call to
+ * _makeInstance().
+ */
+ CtClass clazz = _pool.get(classname);
+ CtClass absClass = updatableClass;
+ CodeConverter converter = new CodeConverter();
+ converter.replaceNew(absClass, absClass, handlerMethod);
+ clazz.instrument(converter);
}
- private void onLoadUpdatable(String classname)
- throws NotFoundException, CannotCompileException
- {
- // if the class is a concrete class,
- // classname is <updatableClassName>$<version>.
-
- int i = classname.lastIndexOf('$');
- if (i <= 0)
- return;
-
- String orgname = classname.substring(0, i);
- if (!orgname.equals(updatableClassName))
- return;
-
- int version;
- try {
- version = Integer.parseInt(classname.substring(i + 1));
- }
- catch (NumberFormatException e) {
- throw new NotFoundException(classname, e);
- }
-
- CtClass clazz = pool.getAndRename(orgname, classname);
- makeConcreteClass(clazz, updatableClass, version);
+ private void onLoadUpdatable(String classname) throws NotFoundException,
+ CannotCompileException {
+ // if the class is a concrete class,
+ // classname is <updatableClassName>$<version>.
+
+ int i = classname.lastIndexOf('$');
+ if (i <= 0)
+ return;
+
+ String orgname = classname.substring(0, i);
+ if (!orgname.equals(updatableClassName))
+ return;
+
+ int version;
+ try {
+ version = Integer.parseInt(classname.substring(i + 1));
+ }
+ catch (NumberFormatException e) {
+ throw new NotFoundException(classname, e);
+ }
+
+ CtClass clazz = pool.getAndRename(orgname, classname);
+ makeConcreteClass(clazz, updatableClass, version);
}
- /* Register an updatable class.
+ /*
+ * Register an updatable class.
*/
- public void makeUpdatable(String classname)
- throws NotFoundException, CannotCompileException
- {
- if (pool == null)
- throw new RuntimeException(
- "Evolution has not been linked to ClassPool.");
-
- CtClass c = pool.get(classname);
- updatableClassName = classname;
- updatableClass = makeAbstractClass(c);
+ public void makeUpdatable(String classname) throws NotFoundException,
+ CannotCompileException {
+ if (pool == null)
+ throw new RuntimeException(
+ "Evolution has not been linked to ClassPool.");
+
+ CtClass c = pool.get(classname);
+ updatableClassName = classname;
+ updatableClass = makeAbstractClass(c);
}
/**
* Produces an abstract class.
*/
protected CtClass makeAbstractClass(CtClass clazz)
- throws CannotCompileException, NotFoundException
- {
- int i;
-
- CtClass absClass = pool.makeClass(clazz.getName());
- absClass.setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT);
- absClass.setSuperclass(clazz.getSuperclass());
- absClass.setInterfaces(clazz.getInterfaces());
-
- // absClass.inheritAllConstructors();
-
- CtField fld = new CtField(pool.get("java.lang.Class"),
- latestVersionField, absClass);
- fld.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
-
- CtField.Initializer finit
- = CtField.Initializer.byCall(
- pool.get("sample.evolve.VersionManager"),
- versionManagerMethod,
- new String[] { clazz.getName() });
- absClass.addField(fld, finit);
-
- CtField[] fs = clazz.getDeclaredFields();
- for (i = 0; i < fs.length; ++i) {
- CtField f = fs[i];
- if (Modifier.isPublic(f.getModifiers()))
- absClass.addField(new CtField(f.getType(), f.getName(),
- absClass));
- }
-
- CtConstructor[] cs = clazz.getDeclaredConstructors();
- for (i = 0; i < cs.length; ++i) {
- CtConstructor c = cs[i];
- int mod = c.getModifiers();
- if (Modifier.isPublic(mod)) {
- CtMethod wm
- = CtNewMethod.wrapped(absClass, handlerMethod,
- c.getParameterTypes(),
- c.getExceptionTypes(),
- trapMethod, null, absClass);
- wm.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
- absClass.addMethod(wm);
- }
- }
-
- CtMethod[] ms = clazz.getDeclaredMethods();
- for (i = 0; i < ms.length; ++i) {
- CtMethod m = ms[i];
- int mod = m.getModifiers();
- if (Modifier.isPublic(mod))
- if (Modifier.isStatic(mod))
- throw new CannotCompileException(
- "static methods are not supported.");
- else {
- CtMethod m2
- = CtNewMethod.abstractMethod(m.getReturnType(),
- m.getName(),
- m.getParameterTypes(),
- m.getExceptionTypes(),
- absClass);
- absClass.addMethod(m2);
- }
- }
-
- return absClass;
+ throws CannotCompileException, NotFoundException {
+ int i;
+
+ CtClass absClass = pool.makeClass(clazz.getName());
+ absClass.setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT);
+ absClass.setSuperclass(clazz.getSuperclass());
+ absClass.setInterfaces(clazz.getInterfaces());
+
+ // absClass.inheritAllConstructors();
+
+ CtField fld = new CtField(pool.get("java.lang.Class"),
+ latestVersionField, absClass);
+ fld.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
+
+ CtField.Initializer finit = CtField.Initializer.byCall(pool
+ .get("sample.evolve.VersionManager"), versionManagerMethod,
+ new String[] { clazz.getName() });
+ absClass.addField(fld, finit);
+
+ CtField[] fs = clazz.getDeclaredFields();
+ for (i = 0; i < fs.length; ++i) {
+ CtField f = fs[i];
+ if (Modifier.isPublic(f.getModifiers()))
+ absClass.addField(new CtField(f.getType(), f.getName(),
+ absClass));
+ }
+
+ CtConstructor[] cs = clazz.getDeclaredConstructors();
+ for (i = 0; i < cs.length; ++i) {
+ CtConstructor c = cs[i];
+ int mod = c.getModifiers();
+ if (Modifier.isPublic(mod)) {
+ CtMethod wm = CtNewMethod.wrapped(absClass, handlerMethod, c
+ .getParameterTypes(), c.getExceptionTypes(),
+ trapMethod, null, absClass);
+ wm.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
+ absClass.addMethod(wm);
+ }
+ }
+
+ CtMethod[] ms = clazz.getDeclaredMethods();
+ for (i = 0; i < ms.length; ++i) {
+ CtMethod m = ms[i];
+ int mod = m.getModifiers();
+ if (Modifier.isPublic(mod))
+ if (Modifier.isStatic(mod))
+ throw new CannotCompileException(
+ "static methods are not supported.");
+ else {
+ CtMethod m2 = CtNewMethod.abstractMethod(m.getReturnType(),
+ m.getName(), m.getParameterTypes(), m
+ .getExceptionTypes(), absClass);
+ absClass.addMethod(m2);
+ }
+ }
+
+ return absClass;
}
/**
- * Modifies the given class file so that it is a subclass of the
- * abstract class produced by makeAbstractClass().
- *
+ * Modifies the given class file so that it is a subclass of the abstract
+ * class produced by makeAbstractClass().
+ *
* Note: the naming convention must be consistent with
* VersionManager.update().
*/
- protected void makeConcreteClass(CtClass clazz,
- CtClass abstractClass, int version)
- throws CannotCompileException, NotFoundException
- {
- int i;
- clazz.setSuperclass(abstractClass);
- CodeConverter converter = new CodeConverter();
- CtField[] fs = clazz.getDeclaredFields();
- for (i = 0; i < fs.length; ++i) {
- CtField f = fs[i];
- if (Modifier.isPublic(f.getModifiers()))
- converter.redirectFieldAccess(f, abstractClass, f.getName());
- }
-
- CtConstructor[] cs = clazz.getDeclaredConstructors();
- for (i = 0; i < cs.length; ++i)
- cs[i].instrument(converter);
-
- CtMethod[] ms = clazz.getDeclaredMethods();
- for (i = 0; i < ms.length; ++i)
- ms[i].instrument(converter);
+ protected void makeConcreteClass(CtClass clazz, CtClass abstractClass,
+ int version) throws CannotCompileException, NotFoundException {
+ int i;
+ clazz.setSuperclass(abstractClass);
+ CodeConverter converter = new CodeConverter();
+ CtField[] fs = clazz.getDeclaredFields();
+ for (i = 0; i < fs.length; ++i) {
+ CtField f = fs[i];
+ if (Modifier.isPublic(f.getModifiers()))
+ converter.redirectFieldAccess(f, abstractClass, f.getName());
+ }
+
+ CtConstructor[] cs = clazz.getDeclaredConstructors();
+ for (i = 0; i < cs.length; ++i)
+ cs[i].instrument(converter);
+
+ CtMethod[] ms = clazz.getDeclaredMethods();
+ for (i = 0; i < ms.length; ++i)
+ ms[i].instrument(converter);
}
}
|