diff --git a/jode/src/net/sf/jode/bytecode/ClassInfo.java b/jode/src/net/sf/jode/bytecode/ClassInfo.java index 7cd368e..6f9b296 100644 --- a/jode/src/net/sf/jode/bytecode/ClassInfo.java +++ b/jode/src/net/sf/jode/bytecode/ClassInfo.java @@ -47,27 +47,42 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -/** - * Accesses, creates or modifies java bytecode classes or interfaces. - * This class represents a class or interface, it can't be used for - * primitive or array types. Every class/interface is associated with - * a class path, which is used to load the class in memory. +/** + * Represents a class or interface. It can't be used for primitive + * or array types. Every class/interface is associated with a class + * path, which is used to load the class and its dependent classes. * - *
setSomething
methods.
+ * setSomething
methods.
+ * setSomething
+ * methods.
+ *
+ * setSomething
methods.
*
- * java.lang.reflect.Modifier
. java.lang.Object
as their super class.
+ * Every class except java.lang.Object
has a super
+ * class. The super class is created in the same classpath as the
+ * current class. Interfaces always have
+ * java.lang.Object
as their super class.
* java.util.Map$Entry
. There are four different types
- * of classes:
+ * the bytecode. However, you can always ignore this inner
+ * information, and access inner classes by their bytecode name,
+ * e.g. java.util.Map$Entry
. There are four different
+ * types of classes:
* getOuterClass()
returns null
and
- * isMethodScoped()
returns false
.
+ * {@link #getOuterClass()} returns null
and
+ * {@link #isMethodScoped()} returns false
.
* getOuterClass()
returns not null
.
+ * {@link #getOuterClass()} returns not null
.
*
- * The bytecode name (getName()
) of an inner class is
- * in most cases of the form Package.Outer$Inner
. But
+ * The bytecode name ({@link #getName()}) of an inner class is
+ * in normally of the form Package.Outer$Inner
. However,
* ClassInfo also supports differently named classes, as long as the
* InnerClass attribute is present. The method
- * getClassName()
returns the name of the inner class
+ * {@link #getClassName()} returns the name of the inner class
* (Inner
in the above example).
*
* You can get all inner classes of a class with the
- * getClasses
method.
+ * method {@link #getClasses}.
* isMethodScoped()
returns true
and
- * getClassName()
returns not null
. In
- * that case getOuterClass()
returns null
,
+ * {@link #isMethodScoped()} returns true
and
+ * {@link #getClassName()} returns not null
. In
+ * that case {@link #getOuterClass()} returns null
,
* too.getName()
) of an method scoped class is
- * in most cases of the form Package.Outer$Number$Inner
. But
+ * The bytecode name ({@link #getName()}) of a method scoped class is
+ * normally of the form Package.Outer$Number$Inner
. However,
* ClassInfo also supports differently named classes, as long as the
* InnerClass attribute is present. isMethodScoped()
returns true
and
- * getClassName()
returns null
. In that
- * case getOuterClass()
returns null
,
+ * {@link #isMethodScoped()} returns true
and
+ * {@link #getClassName()} returns null
. In that
+ * case {@link #getOuterClass()} returns null
,
* too.getName()
) of an method scoped
- * class is in most cases of the form
- * Package.Outer$Number
. But ClassInfo also supports
- * differently named classes, as long as the InnerClass attribute is
- * present. Package.Outer$Number
.
+ * However, ClassInfo also supports differently named classes, as
+ * long as the InnerClass attribute is present. java/lang/String
(type
+ * I represent most types as {@link String} objects (type
* signatures); this is convenient since java bytecode does the same.
* On the other hand a class type should be represented as
- * jode/bytecode/ClassInfo
class. There should be a
- * method to convert to it, but I need a ClassPath for this. Should
- * the method be in ClassInfo (I don't think so), should an instance
- * of TypeSignature have a ClassPath as member variable, or should
- * getClassInfo() take a ClassPath parameter as it is currently?
- * What about arrays, shall we support special ClassInfo's for them,
- * as java.lang.Class does? I think the current solution is okay.
- * HIERARCHY
,
- * PUBLICDECLARATIONS
,
- * DECLARATIONS
, ALMOSTALL
- * or ALL
.
+ * Loads the contents of a class from its class path.
+ * @param howMuch The amount of information that should be loaded
+ * at least, one of {@link #OUTERCLASS}, {@link #HIERARCHY}, {@link
+ * #PUBLICDECLARATIONS}, {@link #DECLARATIONS}, {@link #NODEBUG},
+ * {@link #ALMOSTALL} or {@link #ALL}. Note that more information
+ * than requested can be loaded if this is convenient.
* @exception ClassFormatException if the file doesn't denote a
* valid class.
* @exception FileNotFoundException if class wasn't found in classpath.
- * @exception IOException if an io exception occured.
- * @exception IllegalStateException if this ClassInfo was modified.
- * @see #HIERARCHY
- * @see #PUBLICDECLARATIONS
- * @see #DECLARATIONS
- * @see #ALMOSTALL
- * @see #ALL
+ * @exception IOException if an io exception occured while reading
+ * the class.
+ * @exception SecurityException if a security manager prohibits loading
+ * the class.
+ * @exception IllegalStateException if this ClassInfo was modified by
+ * calling one of the setSomething methods.
*/
public void load(int howMuch)
throws IOException
@@ -975,8 +994,8 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
* extends java.lang.Object, implements no interfaces and has no
* fields, methods or inner classes.
*
- * @param howMuch The amount of information that should be read, e.g.
- * HIERARCHY
.
+ * @param howMuch The amount of information that should be read,
+ * e.g. {@link #HIERARCHY}.
* @see #OUTERCLASS
* @see #HIERARCHY
* @see #PUBLICDECLARATIONS
@@ -1035,9 +1054,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
/**
* This is the counter part to load and guess. It will drop all
- * informations bigger than "keep" and clean up the memory.
+ * informations bigger than "keep" and clean up the memory. Note
+ * that drop should be used with care if more than one thread
+ * accesses this ClassInfo.
* @param keep tells how much info we should keep, can be
- * NONE
or anything that load
accepts.
+ * {@link #NONE} or anything that load
accepts.
* @see #load
*/
public void drop(int keep) {
@@ -1091,6 +1112,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return name;
}
+ /**
+ * Tells whether the information in this class was guessed by a call
+ * to {@link #guess}.
+ * @return true if the information was guessed.
+ */
public boolean isGuessed() {
return isGuessed;
}
@@ -1142,16 +1168,37 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return interfaces;
}
+ /**
+ * Gets the modifiers of this class, e.g. public or abstract. The
+ * information is only available if at least {@link #HIERARCHY} is
+ * loaded.
+ * @return a bitboard of the modifiers.
+ * @see Class#getModifiers
+ * @see Modifier
+ */
public int getModifiers() {
if (modifiers == -1)
throw new IllegalStateException("status is "+status);
return modifiers;
}
+ /**
+ * Checks whether this class info represents an interface. The
+ * information is only available if at least {@link #HIERARCHY} is
+ * loaded.
+ * @return true if this class info represents an interface.
+ */
public boolean isInterface() {
return Modifier.isInterface(getModifiers());
}
+ /**
+ * Searches for a field with given name and type signature.
+ * @param name the name of the field.
+ * @param typeSig the {@link TypeSignature type signature} of the
+ * field.
+ * @return the field info for the field.
+ */
public FieldInfo findField(String name, String typeSig) {
if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status);
@@ -1162,6 +1209,13 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return null;
}
+ /**
+ * Searches for a method with given name and type signature.
+ * @param name the name of the method.
+ * @param typeSig the {@link TypeSignature type signature} of the
+ * method.
+ * @return the method info for the method.
+ */
public MethodInfo findMethod(String name, String typeSig) {
if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status);
@@ -1172,12 +1226,18 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return null;
}
+ /**
+ * Gets the methods of this class.
+ */
public MethodInfo[] getMethods() {
if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status);
return methods;
}
+ /**
+ * Gets the fields (class and member variables) of this class.
+ */
public FieldInfo[] getFields() {
if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status);
@@ -1200,7 +1260,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
}
/**
- * Returns true if the class was declared inside a method.
+ * Tells whether the class was declared inside a method.
* This needs the OUTERCLASS information loaded.
* @return true if this is a method scoped or an anonymous class,
* false otherwise.
@@ -1215,11 +1275,12 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
}
/**
- * Returns the inner classes declared in this class.
+ * Gets the inner classes declared in this class.
* This needs at least PUBLICDECLARATION information loaded.
* @return an array containing the inner classes, guaranteed != null.
* @exception IllegalStateException if PUBLICDECLARATIONS information
- * wasn't loaded yet. */
+ * wasn't loaded yet.
+ */
public ClassInfo[] getClasses() {
if (status < PUBLICDECLARATIONS)
throw new IllegalStateException("status is "+status);
@@ -1457,6 +1518,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return clazz == this;
}
+ /**
+ * Returns a string representation of the class. This is just the
+ * full qualified class name.
+ */
public String toString() {
return name;
}
diff --git a/jode/src/net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java b/jode/src/net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java
index a3223e6..3686b1a 100644
--- a/jode/src/net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java
+++ b/jode/src/net/sf/jode/obfuscator/modules/LocalizeFieldTransformer.java
@@ -26,10 +26,7 @@ import net.sf.jode.obfuscator.*;
*/
public class LocalizeFieldTransformer implements CodeTransformer {
- public static void transformCode(BytecodeInfo bytecode) {
- for (Instruction instr = bytecode.getFirstInstr();
- instr != null; instr = instr.nextByAddr) {
-
- }
+ public void transformCode(BasicBlocks bb) {
+ /* XXX implement */
}
}
diff --git a/jode/src/net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java b/jode/src/net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java
index 364ac2b..8152c8e 100644
--- a/jode/src/net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java
+++ b/jode/src/net/sf/jode/obfuscator/modules/RemovePopAnalyzer.java
@@ -186,13 +186,13 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
(Instruction.forOpcode(opc_pop)); //DCABD<
newInstructions.addFirst
(Instruction.forOpcode(opc_dup2_x2)); //DCABDC<
- swappedBeforeDup = !swappedBeforeDup //ABDC<
+ swappedBeforeDup = !swappedBeforeDup; //ABDC<
}
if (swapBeforeDup)
newInstructions.addFirst
(Instruction.forOpcode(opc_swap));
- return newPopped
+ return newPopped;
}
/**
@@ -369,7 +369,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
blocks[i].setCode((Instruction[]) newInstructions
.toArray(new Instruction[newInstructions.size()]),
blocks[i].getSuccs());
- return poppedEntries
+ return poppedEntries;
}
/**
@@ -399,143 +399,7 @@ public class RemovePopAnalyzer implements CodeTransformer, Opcodes {
Instruction instr = oldInstrs[--instrNr];
instr.getStackPopPush(poppush);
- for (stackDepth
-
- /* Check if this instr pushes a popped Entry. */
- boolean pops_a_popped = false;
- boolean pops_all_popped = true;
- for (int j=0; j < poppush[1]; j++) {
- if (poppedEntries.get(j))
- push_a_popped = true;
- else
- push_all_popped = false;
- }
-
- if (!push_a_popped) {
- // Normal case:
- // add the instruction and adjust stack depth.
- newInstructions.addFirst(instr);
- stackDepth += poppush[0] - poppush[1];
- continue;
- }
-
- /* We push an entry, that gets popped later */
- int opcode = instr.getOpcode();
- switch (opcode) {
- case opc_dup:
- case opc_dup_x1:
- case opc_dup_x2:
- case opc_dup2:
- case opc_dup2_x1:
- case opc_dup2_x2: {
- int popped = 0;
- for (int j = poppush[1] ; j > 0; j--) {
- popped <<= 1;
- if (poppedEntries.get(--stackDepth)) {
- popped |= 1;
- poppedEntries.clear(stackDepth);
- }
- }
- popped = movePopsThroughDup(opcode, newInstructions,
- popped);
- for (int j=0; j < poppush[1]; j++) {
- if ((popped & 1) != 0)
- poppedEntries.set(stackDepth);
- stackDepth++;
- popped >>=1;
- }
- break;
- }
-
- case opc_swap:
- if (!push_all_popped) {
- // swap the popped status
- if (poppedEntries.get(stackDepth - 1)) {
- poppedEntries.clear(stackDepth - 1);
- poppedEntries.set(stackDepth - 2);
- } else {
- poppedEntries.set(stackDepth - 1);
- poppedEntries.clear(stackDepth - 2);
- }
- }
-
- case opc_ldc2_w:
- case opc_lload: case opc_dload:
- case opc_i2l: case opc_i2d:
- case opc_f2l: case opc_f2d:
- case opc_ldc:
- case opc_iload: case opc_fload: case opc_aload:
- case opc_new:
- case opc_lneg: case opc_dneg:
- case opc_l2d: case opc_d2l:
- case opc_laload: case opc_daload:
- case opc_ineg: case opc_fneg:
- case opc_i2f: case opc_f2i:
- case opc_i2b: case opc_i2c: case opc_i2s:
- case opc_newarray: case opc_anewarray:
- case opc_arraylength:
- case opc_instanceof:
- case opc_lshl: case opc_lshr: case opc_lushr:
- case opc_iaload: case opc_faload: case opc_aaload:
- case opc_baload: case opc_caload: case opc_saload:
- case opc_iadd: case opc_fadd:
- case opc_isub: case opc_fsub:
- case opc_imul: case opc_fmul:
- case opc_idiv: case opc_fdiv:
- case opc_irem: case opc_frem:
- case opc_iand: case opc_ior : case opc_ixor:
- case opc_ishl: case opc_ishr: case opc_iushr:
- case opc_fcmpl: case opc_fcmpg:
- case opc_l2i: case opc_l2f:
- case opc_d2i: case opc_d2f:
- case opc_ladd: case opc_dadd:
- case opc_lsub: case opc_dsub:
- case opc_lmul: case opc_dmul:
- case opc_ldiv: case opc_ddiv:
- case opc_lrem: case opc_drem:
- case opc_land: case opc_lor : case opc_lxor:
- case opc_lcmp:
- case opc_dcmpl: case opc_dcmpg:
- case opc_getstatic:
- case opc_getfield:
- case opc_multianewarray:
-
- /* The simple instructions, that can be removed. */
- if (!push_all_popped)
- throw new InternalError("pop half of a long");
- if (poppush[0] < poppush[1]) {
- for (int j=0; j < poppush[0] - poppush[1]; j++)
- poppedEntries.set(stackDepth++);
- } else if (poppush[0] < poppush[1]) {
- for (int j=0; j < poppush[0] - poppush[1]; j++)
- poppedEntries.clear(--stackDepth);
- }
-
- case opc_invokevirtual:
- case opc_invokespecial:
- case opc_invokestatic:
- case opc_invokeinterface:
- case opc_checkcast:
-
- /* These instructions can't be removed, since
- * they have side effects.
- */
- if (!push_all_popped)
- throw new InternalError("pop half of a long");
- if (poppush[1] == 1) {
- poppedEntries.clear(--stackDepth);
- newInstructions
- .addFirst(Instruction.forOpcode(opc_pop));
- } else {
- poppedEntries.clear(--stackDepth);
- poppedEntries.clear(--stackDepth);
- newInstructions
- .addFirst(Instruction.forOpcode(opc_pop2));
- }
- newInstructions.addFirst(instr);
- default:
- throw new InternalError("Unexpected opcode!");
- }
+ /* XXX handle pops inside a opc_dup */
}
block.setCode((Instruction[]) newInstructions
.toArray(new Instruction[newInstructions.size()]),