Browse Source

implemented pruning


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@125 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 20 years ago
parent
commit
8c82477b41

+ 8
- 2
src/main/javassist/ClassPool.java View File

@@ -37,6 +37,8 @@ import java.util.Hashtable;
* of memory. To avoid this, a <code>ClassPool</code> object
* should be recreated, for example, every hundred classes processed.
* Note that <code>getDefault()</code> is a singleton factory.
* Otherwise, <code>detach()</code> in <code>CtClass</code> should be used
* to avoid huge memory consumption.
*
* <p><b><code>ClassPool</code> hierarchy:</b>
*
@@ -75,6 +77,8 @@ public class ClassPool {
*/
private Hashtable cflow = null; // should be synchronous.

private static final int INIT_HASH_SIZE = 191;

/**
* Creates a root class pool. No parent class pool is specified.
*
@@ -91,7 +95,7 @@ public class ClassPool {
* @see javassist.ClassPool#getDefault()
*/
public ClassPool(ClassPool parent) {
this.classes = new Hashtable();
this.classes = new Hashtable(INIT_HASH_SIZE);
this.source = new ClassPoolTail();
this.parent = parent;
if (parent == null) {
@@ -289,8 +293,10 @@ public class ClassPool {

if (clazz == null)
throw new NotFoundException(classname);
else
else {
clazz.incGetCounter();
return clazz;
}
}

/**

+ 1
- 1
src/main/javassist/CtBehavior.java View File

@@ -355,7 +355,7 @@ public abstract class CtBehavior extends CtMember {
throws CannotCompileException
{
// if the class is not frozen,
// does not trun the modified flag on.
// does not turn the modified flag on.
if (declaringClass.isFrozen())
declaringClass.checkModify();


+ 36
- 3
src/main/javassist/CtClass.java View File

@@ -241,17 +241,48 @@ public abstract class CtClass {
/**
* Defrosts the class so that the class can be modified again.
*
* To avoid changes that will be never reflected,
* <p>To avoid changes that will be never reflected,
* the class is frozen to be unmodifiable if it is loaded or
* written out. This method should be called only in a case
* that the class will be reloaded or written out later again.
*
* <p>If <code>defrost()</code> will be called later, pruning
* must be disallowed in advance.
*
* @see #isFrozen()
* @see #stopPruning(boolean)
*/
public void defrost() {
throw new RuntimeException("cannot defrost " + getName());
}

/**
* Disallows (or allows) pruning the data structure on memory
* when this <code>CtClass</code> object is converted into a class file.
* Pruning saves memory space since a <code>ClassPool</code> holds
* all instances of <code>CtClass</code>
* all the time of program execution.
* However, pruning discards the data representing part of the
* class definition, such as method bodies.
* Therefore, once it is pruned, <code>toBytecode()</code>,
* <code>writeFile()</code>, or <code>toClass()</code> cannot
* be called again.
*
* <p>Initially, pruning is allowed.
*
* @param stop disallow pruning if true. Otherwise, allow.
* @see #detach()
* @see #toBytecode()
* @see #toClass()
* @see #writeFile()
*/
public void stopPruning(boolean stop) {}

/* Called by get() in ClassPool.
* CtClassType overrides this method.
*/
void incGetCounter() {}

/**
* Returns <code>true</code> if this object represents a primitive
* Java type: boolean, byte, char, short, int, long, float, double,
@@ -904,11 +935,13 @@ public abstract class CtClass {
}

/**
* Removes this <code>CtClass</code> from the <code>ClassPool</code>.
* Removes this <code>CtClass</code> object from the
* <code>ClassPool</code>.
* After this method is called, any method cannot be called on the
* removed <code>CtClass</code> object.
*
* <p>If needed,
* <p>If <code>get()</code> in <code>ClassPool</code> is called
* with the name of the removed method,
* the <code>ClassPool</code> will read the class file again
* and constructs another <code>CtClass</code> object representing
* the same class.

+ 65
- 4
src/main/javassist/CtClassType.java View File

@@ -29,6 +29,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.List;

/**
@@ -37,7 +38,8 @@ import java.util.List;
class CtClassType extends CtClass {
ClassPool classPool;
boolean wasChanged;
boolean wasFrozen;
private boolean wasFrozen;
boolean wasPruned;
ClassFile classfile;

private CtField fieldsCache;
@@ -51,16 +53,22 @@ class CtClassType extends CtClass {
private Hashtable hiddenMethods; // must be synchronous
private int uniqueNumberSeed;

private boolean doPruning = true;
int getCounter;
private static int readCounter = 0;
private static final int READ_THRESHOLD = 100; // see getClassFile2()

CtClassType(String name, ClassPool cp) {
super(name);
classPool = cp;
wasChanged = wasFrozen = false;
wasChanged = wasFrozen = wasPruned = false;
classfile = null;
accessors = null;
fieldInitializers = null;
hiddenMethods = null;
uniqueNumberSeed = 0;
eraseCache();
getCounter = 0;
}

CtClassType(InputStream ins, ClassPool cp) throws IOException {
@@ -76,6 +84,9 @@ class CtClassType extends CtClass {
if (wasFrozen)
buffer.append("frozen ");

if (wasPruned)
buffer.append("pruned ");

buffer.append(Modifier.toString(getModifiers()));
buffer.append(" class ");
buffer.append(getName());
@@ -149,6 +160,11 @@ class CtClassType extends CtClass {
if (classfile != null)
return classfile;

if (readCounter++ > READ_THRESHOLD) {
doCompaction();
readCounter = 0;
}

InputStream fin = null;
try {
fin = classPool.openClassfile(getName());
@@ -174,6 +190,28 @@ class CtClassType extends CtClass {
}
}

/* Inherited from CtClass. Called by get() in ClassPool.
*
* @see javassist.CtClass#incGetCounter()
*/
void incGetCounter() { ++getCounter; }

private void doCompaction() {
Enumeration e = classPool.classes.elements();
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof CtClassType) {
CtClassType cct = (CtClassType)obj;
if (cct.getCounter < 2 && !cct.isModified()) {
cct.eraseCache();
cct.classfile = null;
}

cct.getCounter = 0;
}
}
}

public ClassPool getClassPool() { return classPool; }

void setClassPool(ClassPool cp) { classPool = cp; }
@@ -197,7 +235,10 @@ class CtClassType extends CtClass {
wasChanged = true;
}

public void defrost() { wasFrozen = false; }
public void defrost() {
checkPruned("defrost");
wasFrozen = false;
}

public boolean subtypeOf(CtClass clazz) throws NotFoundException {
int i;
@@ -855,15 +896,25 @@ class CtClassType extends CtClass {
{
try {
if (isModified()) {
checkPruned("toBytecode");
ClassFile cf = getClassFile2();
modifyClassConstructor(cf);
modifyConstructors(cf);
cf.write(out);
out.flush();
fieldInitializers = null;
if (doPruning) {
// to save memory
cf.prune();
wasPruned = true;
}
}
else
else {
classPool.writeClassfile(getName(), out);
// to save memory
eraseCache();
classfile = null;
}

wasFrozen = true;
}
@@ -875,6 +926,16 @@ class CtClassType extends CtClass {
}
}

private void checkPruned(String method) {
if (wasPruned)
throw new RuntimeException(method + "(): " + getName()
+ " was pruned.");
}

public void stopPruning(boolean stop) {
doPruning = !stop;
}

private void modifyClassConstructor(ClassFile cf)
throws CannotCompileException, NotFoundException
{

+ 1
- 0
src/main/javassist/CtNewClass.java View File

@@ -61,6 +61,7 @@ class CtNewClass extends CtClassType {
if (!hasConstructor)
try {
inheritAllConstructors();
hasConstructor = true;
}
catch (NotFoundException e) {
throw new CannotCompileException(e);

+ 2
- 2
src/main/javassist/bytecode/AnnotationsAttribute.java View File

@@ -84,7 +84,7 @@ public class AnnotationsAttribute extends AttributeInfo {
* @param cp constant pool
* @param attrname attribute name (<code>visibleTag</code> or
* <code>invisibleTag</code>).
* @see #setAnnotations(Annotations[])
* @see #setAnnotations(Annotation[])
*/
public AnnotationsAttribute(ConstPool cp, String attrname) {
this(cp, attrname, new byte[] { 0, 0 });
@@ -127,7 +127,7 @@ public class AnnotationsAttribute extends AttributeInfo {
* this object unless the tree is copied back to this object by
* <code>setAnnotations()</code>.
*
* @see #setAnnotations()
* @see #setAnnotations(Annotation[])
*/
public Annotation[] getAnnotations() {
try {

+ 36
- 0
src/main/javassist/bytecode/ClassFile.java View File

@@ -98,6 +98,42 @@ public final class ClassFile {
return qname + ".java";
}

/**
* Discards all attributes, associated with both the class file and
* the members such as a code attribute and exceptions attribute.
* The unused constant pool entries are also discarded (a new packed
* constant pool is constructed).
*/
public void prune() {
ConstPool cp = new ConstPool(thisclassname);
superClass = cp.addClassInfo(getSuperclass());

if (interfaces != null) {
int n = interfaces.length;
for (int i = 0; i < n; ++i)
interfaces[i]
= cp.addClassInfo(constPool.getClassInfo(interfaces[i]));
}

ArrayList list = methods;
int n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
minfo.prune(cp);
}

list = fields;
n = list.size();
for (int i = 0; i < n; ++i) {
FieldInfo finfo = (FieldInfo)list.get(i);
finfo.prune(cp);
}

attributes = new LinkedList();
cp.prune();
constPool = cp;
}

/**
* Returns a constant pool table.
*/

+ 5
- 0
src/main/javassist/bytecode/ConstPool.java View File

@@ -124,6 +124,11 @@ public final class ConstPool {
read(in);
}

void prune() {
classes = new HashMap();
strings = new HashMap();
}

/**
* Returns the name of the class using this constant pool table.
*/

+ 7
- 0
src/main/javassist/bytecode/FieldInfo.java View File

@@ -59,6 +59,13 @@ public final class FieldInfo {
read(in);
}

void prune(ConstPool cp) {
attribute = null;
name = cp.addUtf8Info(getName());
descriptor = cp.addUtf8Info(getDescriptor());
constPool = cp;
}

/**
* Returns the constant pool table used
* by this <code>field_info</code>.

+ 7
- 0
src/main/javassist/bytecode/MethodInfo.java View File

@@ -95,6 +95,13 @@ public final class MethodInfo {
read(src, methodname, classnameMap);
}

void prune(ConstPool cp) {
attribute = null;
name = cp.addUtf8Info(getName());
descriptor = cp.addUtf8Info(getDescriptor());
constPool = cp;
}

/**
* Returns a method name.
*/

+ 1
- 1
src/main/javassist/bytecode/ParameterAnnotationsAttribute.java View File

@@ -123,7 +123,7 @@ public class ParameterAnnotationsAttribute extends AttributeInfo {
* @return Each element of the returned array represents an array of
* annotations that are associated with each method parameter.
*
* @see #setAnnotations()
* @see #setAnnotations(Annotation[][])
*/
public Annotation[][] getAnnotations() {
try {

+ 3
- 5
src/main/javassist/bytecode/annotation/AnnotationsWriter.java View File

@@ -23,7 +23,6 @@ import javassist.bytecode.ConstPool;
/**
* A convenience class for constructing a
* <code>..Annotations_attribute</code>.
* It is typically used together with <code>AnnotationsVisitor</code>.
* See the source code of the <code>AnnotationsAttribute.Copier</code> class.
*
* <p>The following code snippet is an example of use of this class:
@@ -51,12 +50,11 @@ import javassist.bytecode.ConstPool;
* corresponding to this annotation:
*
* <ul><pre>
* @Author(name = "chiba", address = "tokyo")
* &nbsp;@Author(name = "chiba", address = "tokyo")
* </pre></ul>
*
* @see AnnotationsAttribute
* @see ParameterAnnotationsAttribute
* @see AnnotationsVisitor
* @see javassist.bytecode.AnnotationsAttribute
* @see javassist.bytecode.ParameterAnnotationsAttribute
*/
public class AnnotationsWriter {
private OutputStream output;

+ 1
- 1
src/main/javassist/bytecode/annotation/EnumMemberValue.java View File

@@ -64,7 +64,7 @@ public class EnumMemberValue extends MemberValue {
/**
* Changes the enum type name.
*
* @param classname a fully-qualified type name.
* @param typename a fully-qualified type name.
*/
public void setType(String typename) {
typeIndex = cp.addUtf8Info(Descriptor.of(typename));

+ 1
- 1
src/main/javassist/compiler/MemberCodeGen.java View File

@@ -464,7 +464,7 @@ public class MemberCodeGen extends CodeGen {
if (maker != null)
return maker.getConstructor(declClass, desc, minfo);
}
throw new CompileError("the called constructor is private in "
+ declClass.getName());
}

+ 2
- 2
src/main/javassist/reflect/ClassMetaobject.java View File

@@ -332,14 +332,14 @@ public class ClassMetaobject implements Serializable {
* to the original method in the reflected class (i.e. not the proxy
* method), using the original name of the method.
*
* <p>Written by Brett Randall and Shigeru Chiba.
*
* @param originalName The original name of the reflected method
* @param argTypes array of Class specifying the method signature
* @return the identifier index of the original method
* @throws NoSuchMethodException if the method does not exist
*
* @see ClassMetaobject#getMethod(int)
* @author Brett Randall
* @author Shigeru Chiba
*/
public final int getMethodIndex(String originalName, Class[] argTypes)
throws NoSuchMethodException

Loading…
Cancel
Save