* ConstantInstruction.java,IncInstruction.java,ReferenceInstruction.java,SlotInstruction.java,TypeDimensionInstruction.java,TypeInstruction.java: Class and Constructors no longer public.

* Instruction.java (forOpcode): added method to create instructions.
* SlotInstruction.java,IncInstruction.java: Use a LocalVariableInfo
  entry instead of slot+addr
* BasicBlockReader.java, BasicBlockWriter.java:  Adapted Instruction interface.
* BinaryInfo.java: package private class now.
* BinaryInfo.java,FieldInfo.java,MethodInfo.java: Made some methods
  package private.
* BasicBlocks.java (getAllInstructions): removed.
  (read,readAttribute): no longer protected.
* ClassInfo.java (isGuessed): added.

All classes: bug fixes, etc.


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1266 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 25 years ago
parent ca386721b2
commit 5e6af53990
  1. 47
      jode/jode/bytecode/BasicBlockReader.java
  2. 31
      jode/jode/bytecode/BasicBlockWriter.java
  3. 84
      jode/jode/bytecode/BasicBlocks.java
  4. 55
      jode/jode/bytecode/BinaryInfo.java
  5. 112
      jode/jode/bytecode/Block.java
  6. 65
      jode/jode/bytecode/ClassInfo.java
  7. 10
      jode/jode/bytecode/ClassPath.java
  8. 17
      jode/jode/bytecode/ConstantInstruction.java
  9. 30
      jode/jode/bytecode/FieldInfo.java
  10. 2
      jode/jode/bytecode/Handler.java
  11. 18
      jode/jode/bytecode/IncInstruction.java
  12. 245
      jode/jode/bytecode/Instruction.java
  13. 15
      jode/jode/bytecode/MethodInfo.java
  14. 23
      jode/jode/bytecode/ReferenceInstruction.java
  15. 28
      jode/jode/bytecode/SlotInstruction.java
  16. 15
      jode/jode/bytecode/SwitchInstruction.java
  17. 22
      jode/jode/bytecode/TypeDimensionInstruction.java
  18. 20
      jode/jode/bytecode/TypeInstruction.java
  19. 2
      jode/jode/bytecode/package.html

@ -256,7 +256,7 @@ class BasicBlockReader implements Opcodes {
if (!alwaysJump)
succs[succLength] = getSuccBlock(info.nextAddr);
blocks[blockNr].setCode(Arrays.asList(instrs), succs);
blocks[blockNr].setCode(instrs, succs);
}
void convert() throws ClassFormatException {
@ -331,7 +331,9 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
instr = new SlotInstruction(wideopcode, slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction(wideopcode, lvi);
length = 4;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -345,7 +347,9 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals-1)
throw new ClassFormatException
("Invalid local slot "+slot);
instr = new SlotInstruction(wideopcode, slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction(wideopcode, lvi);
length = 4;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -358,7 +362,9 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
instr = new SlotInstruction(wideopcode, slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction(wideopcode, lvi);
length = 4;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -370,8 +376,10 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
int incr = input.readShort();
instr = new IncInstruction(wideopcode, slot, incr);
instr = new IncInstruction(wideopcode, lvi, incr);
length = 6;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -399,8 +407,10 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction
(opc_iload + (opcode-opc_iload_0)/4, slot);
(opc_iload + (opcode-opc_iload_0)/4, lvi);
length = 1;
break;
}
@ -414,8 +424,10 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction
(opc_istore + (opcode-opc_istore_0)/4, slot);
(opc_istore + (opcode-opc_istore_0)/4, lvi);
length = 1;
break;
}
@ -427,8 +439,10 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals-1)
throw new ClassFormatException
("Invalid local slot "+slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction
(opc_lstore + (opcode-opc_lstore_0)/4, slot);
(opc_lstore + (opcode-opc_lstore_0)/4, lvi);
length = 1;
break;
}
@ -438,7 +452,9 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
instr = new SlotInstruction(opcode, slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction(opcode, lvi);
length = 2;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -451,7 +467,9 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals - 1)
throw new ClassFormatException
("Invalid local slot "+slot);
instr = new SlotInstruction(opcode, slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction(opcode, lvi);
length = 2;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -463,7 +481,9 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
instr = new SlotInstruction(opcode, slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
instr = new SlotInstruction(opcode, lvi);
length = 2;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -535,8 +555,10 @@ class BasicBlockReader implements Opcodes {
if (slot >= maxLocals)
throw new ClassFormatException
("Invalid local slot "+slot);
LocalVariableInfo lvi
= LocalVariableInfo.getInfo(slot);
int incr = input.readByte();
instr = new IncInstruction(opcode, slot, incr);
instr = new IncInstruction(opcode, lvi, incr);
length = 3;
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_BYTECODE) != 0)
@ -958,3 +980,4 @@ class BasicBlockReader implements Opcodes {
}
}
}

@ -89,11 +89,10 @@ class BasicBlockWriter implements Opcodes {
int blockNr = block.getBlockNr();
LocalVariableInfo[] life
= (LocalVariableInfo[]) atStart[blockNr].clone();
for (Iterator iter = block.getInstructions().iterator();
iter.hasNext() ; ) {
Instruction instr = (Instruction) iter.next();
if (instr.hasLocal()) {
LocalVariableInfo lvi = instr.getLocalInfo();
Instruction[] instrs = block.getInstructions();
for (int i = 0; i < instrs.length; i++) {
if (instrs[i].hasLocal()) {
LocalVariableInfo lvi = instrs[i].getLocalInfo();
int slot = lvi.getSlot();
if (life[slot] != null
&& life[slot] != lvi)
@ -162,10 +161,9 @@ class BasicBlockWriter implements Opcodes {
}
}
int size = block.getInstructions().size();
for (int k = 0; k < size; k++) {
Instruction instr
= (Instruction) block.getInstructions().get(k);
Instruction[] instrs = block.getInstructions();
for (int k = 0; k < instrs.length; k++) {
Instruction instr = instrs[k];
if (instr.hasLocal()) {
LocalVariableInfo lvi = instr.getLocalInfo();
int slot = lvi.getSlot();
@ -227,12 +225,11 @@ class BasicBlockWriter implements Opcodes {
next_block:
for (int i = 0; i < blocks.length; i++) {
blockAddr[i] = addr;
List instructions = blocks[i].getInstructions();
int size = instructions.size();
instrLength[i] = new int[size];
Instruction[] instrs = blocks[i].getInstructions();
instrLength[i] = new int[instrs.length];
Block[] succs = blocks[i].getSuccs();
for (int j = 0; j < size; j++) {
Instruction instr = (Instruction) instructions.get(j);
for (int j = 0; j < instrs.length; j++) {
Instruction instr = instrs[j];
if (instr.hasLineNr())
lntCount++;
@ -637,10 +634,10 @@ class BasicBlockWriter implements Opcodes {
Block[] succs = blocks[i].getSuccs();
if (addr != blockAddr[i])
throw new InternalError("Address calculation broken!");
List instructions = blocks[i].getInstructions();
int size = instructions.size();
Instruction[] instructions = blocks[i].getInstructions();
int size = instructions.length;
for (int j = 0; j < size; j++) {
Instruction instr = (Instruction) instructions.get(j);
Instruction instr = instructions[j];
if (instr.hasLineNr()) {
lnt[lntPtr++] = (short) addr;
lnt[lntPtr++] = (short) instr.getLineNr();

@ -1,4 +1,4 @@
/* BasicBlocks Copyright (C) 1999 Jochen Hoenicke.
/* BasicBlocks Copyright (C) 2000 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,6 +28,7 @@ import java.io.PrintWriter;
///#def COLLECTIONS java.util
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
///#enddef
@ -36,22 +37,37 @@ import java.lang.UnsupportedOperationException;
///#enddef
/**
* <p>This class gives another representation of the byte code of a
* method. The instructions are splitted into BasicBlocks, each an
* array of consecutive Instructions. It is not allowed that a goto
* jumps inside a basic block.</p>
* <p>Represents the byte code of a method in form of basic blocks. A
* basic block is a bunch of instructions, that must always execute in
* sequential order. Every basic block is represented by an Block
* object.</p>
*
* <p>All jumps must be at the end of the block. A conditional jump
* may be followed by a single goto, but there must not be any other
* jumps. If there is now unconditional jump at the end, the block
* implicitely flows into the next one. </p>
* <p>All jump instructions must be at the end of the block, and the
* jump instructions doesn't have to remember where they jump to.
* Instead this information is stored inside the blocks. See
* <code>Block</code> for details.</p>
*
* <p>Try block must span over some consecutive BasicBlocks and there
* catches must jump to the start of an basic block. </p>
* <p>A subroutine block, i.e. a block where some jsr instructions may
* jump to, must store its return address in a local variable
* immediately. There must be exactly one block with the
* corresponding <code>opc_ret</code> instruction and all blocks that
* belong to this subroutine must point to the ret block. Bytecode
* that doesn't have this condition is automatically transformed on
* reading.</p>
*
* <p>Deadcode will not be included in the BasicBlock, also
* BasicBlocks consisting of a single jump will be optimized away.</p>
* <p>Exception Handlers are represented by the Handler class. Their
* start/end range must span over some consecutive BasicBlocks and
* there handler must be another basic block.</p>
*
* <p>If you want to create or modify the byte code, you must first set
* the basic blocks and then set exception handlers. If you set new
* blocks the previous exception handlers will be removed.</p>
*
* <p>When the code is written to a class file, the blocks are written
* in the given order. Goto and return instructions are inserted as
* necessary, you don't have to care about that.</p>
*
* @see jode.bytecode.Block
* @see jode.bytecode.Instruction */
public class BasicBlocks extends BinaryInfo {
@ -121,39 +137,6 @@ public class BasicBlocks extends BinaryInfo {
return blocks;
}
public Iterator getAllInstructions() {
return new Iterator() {
int blockNr = 0;
Iterator blockIter = getNextIterator();
public boolean hasNext() {
return blockIter != null;
}
public Iterator getNextIterator() {
if (blockNr < blocks.length)
return blocks[blockNr++].getInstructions().iterator();
return null;
}
public Object next() {
Object instr;
try {
instr = blockIter.next();
} catch (NullPointerException ex) {
throw new NoSuchElementException();
}
if (!blockIter.hasNext())
blockIter = getNextIterator();
return instr;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/**
* @return the exception handlers, or null if the method has no
* exception handlers.
@ -215,7 +198,7 @@ public class BasicBlocks extends BinaryInfo {
}
private BasicBlockReader reader;
public void read(ConstantPool cp,
void read(ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if ((GlobalOptions.debuggingFlags
@ -231,7 +214,7 @@ public class BasicBlocks extends BinaryInfo {
dumpCode(GlobalOptions.err);
}
protected void readAttribute(String name, int length, ConstantPool cp,
void readAttribute(String name, int length, ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if (howMuch >= ClassInfo.ALMOSTALL
@ -248,7 +231,8 @@ public class BasicBlocks extends BinaryInfo {
void reserveSmallConstants(GrowableConstantPool gcp) {
for (int i=0; i < blocks.length; i++) {
next_instr:
for (Iterator iter = blocks[i].getInstructions().iterator();
for (Iterator iter
= Arrays.asList(blocks[i].getInstructions()).iterator();
iter.hasNext(); ) {
Instruction instr = (Instruction) iter.next();
if (instr.getOpcode() == Opcodes.opc_ldc) {
@ -293,7 +277,7 @@ public class BasicBlocks extends BinaryInfo {
writeAttributes(gcp, output);
bbw = null;
}
public void dumpCode(PrintWriter output) {
output.println(methodInfo.getName()+methodInfo.getType()+":");
if (startBlock == null)

@ -34,10 +34,26 @@ import java.util.Iterator;
/**
* <p>Represents a container for user specified attributes.</p>
*
* @author Jochen Hoenicke
* <p>Java bytecode is extensible: Classes, Methods and Fields may
* have any number of attributes. Every attribute has a name and some
* unformatted data.</p>
*
* <p>There are some predefined attributes, even the Code of a Method
* is an attribute. These predefined attributes are all handled by
* this package as appropriate. This methods are only useful for non
* standard attributes.</p>
*
* <p>One application of this attributes are installation classes.
* These classes have a special attribute containing a zip of the
* files that should be installed. There are other possible uses,
* e.g. putting native machine code for some architectures into the
* class.</p>
*
* @author Jochen Hoenicke
*/
class BinaryInfo {
public class BinaryInfo {
private Map unknownAttributes = null;
void skipAttributes(DataInputStream input) throws IOException {
@ -140,8 +156,9 @@ class BinaryInfo {
}
}
public void dropAttributes() {
unknownAttributes = null;
void drop(int keep) {
if (keep < ClassInfo.ALL)
unknownAttributes = null;
}
void prepareAttributes(GrowableConstantPool gcp) {
@ -178,7 +195,7 @@ class BinaryInfo {
}
}
public int getAttributeSize() {
int getAttributeSize() {
int size = 2; /* attribute count */
if (unknownAttributes != null) {
Iterator i = unknownAttributes.values().iterator();
@ -188,31 +205,55 @@ class BinaryInfo {
return size;
}
/**
* Finds a non standard attribute with the given name.
* @param name the name of the attribute.
* @return the contents of the attribute, null if not found.
*/
public byte[] findAttribute(String name) {
if (unknownAttributes != null)
return (byte[]) unknownAttributes.get(name);
return null;
}
/**
* Gets all non standard attributes
*/
public Iterator getAttributes() {
if (unknownAttributes != null)
return unknownAttributes.values().iterator();
return Collections.EMPTY_SET.iterator();
}
public void setAttribute(String name, byte[] content) {
/**
* Adds a new non standard attribute or replaces an old one with the
* same name.
* @param name the name of the attribute.
* @param contents the new contens.
*/
public void setAttribute(String name, byte[] contents) {
if (unknownAttributes == null)
unknownAttributes = new SimpleMap();
unknownAttributes.put(name, content);
unknownAttributes.put(name, contents);
}
/**
* Removes a new non standard attribute.
* @param name the name of the attribute.
* @return the old contents of the attribute.
*/
public byte[] removeAttribute(String name) {
if (unknownAttributes != null)
return (byte[]) unknownAttributes.remove(name);
return null;
}
/**
* Removes all non standard attribute.
*/
public void removeAllAttributes() {
unknownAttributes = null;
}
}

@ -1,4 +1,4 @@
/* Block Copyright (C) 1999 Jochen Hoenicke.
/* Block Copyright (C) 2000 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -28,12 +28,48 @@ import java.util.Iterator;
///#enddef
/**
* Represents a single basic block. It contains a list of
* instructions, the successor blocks and the exception handlers for
* this block. The last Instruction, and only the last, may be a
* conditional jump, a tableswitch or a jsr.
* <p>Represents a single basic block. It contains a list of
* instructions and the successor blocks.</p>
*
* @author Jochen Hoenicke */
* <p>All jump instructions must be at the end of the block. These
* jump instructions are <code>opc_lookupswitch</code>,
* <code>opc_if</code>xxx, <code>opc_jsr</code>, <code>opc_ret</code>,
* <code>opc_</code>x<code>return</code> and <code>opc_return</code>.
* An <code>opc_goto</code> is implicit if the basic block doesn't end
* with a jump instructions, or if it ends with an conditional jump or
* jsr.</p>
*
* <p>The jump instructions don't remember their destinations, instead
* the Block does it. This are the successor block. There are
* several cases:</p>
*
* <ul>
* <li>Block ends with <code>opc_lookupswitch</code> with
* <code>n</code> values. Then there must be <code>n+1</code>
* successors where the first <code>n</code> successors correspond to
* the values and the last successor is the default successor.</li>
* <li>Block ends with <code>opc_if</code>xxx, then there must be two
* successors: The first one is the successor if the condition evaluates
* to true, the second one is for the false branch. </li>
* <li>Block ends with <code>opc_jsr</code>, then there must be two
* successors: The first one is the subroutine, the second is the next
* block after the subroutine. </li>
* <li>Block ends with <code>opc_</code>x</code>return</code> or
* <code>opc_ret</code>, then there must no successor at all. </li>
* <li>In any other case there must be exactly one successor.</li>
* </ul>
*
* <p>If any successor is <code>null</code> it represents end of
* method, i.e. a return instruction. You can also use
* <code>null</code> successors for conditional jumps and switch
* instruction. You normally shouldn't use <code>opc_return</code>
* instructions. They are only necessary, if you want to return with
* a non-empty stack. </p>
*
* @author Jochen Hoenicke
* @see jode.bytecode.BasicBlocks
* @see jode.bytecode.Instruction
*/
public final class Block {
/**
* The opcodes of the instructions in this block.
@ -55,6 +91,21 @@ public final class Block {
*/
int blockNr;
/**
* The blockNr of this block. Set by BasicBlocks.
*/
int lineNr;
/**
* The number of items this block takes from the stack.
*/
int pop;
/**
* The number of items this block puts on the stack.
*/
int push;
/**
* Creates a new empty block, with a null successor array.
*/
@ -68,8 +119,8 @@ public final class Block {
* modified, except that the instructions (but not their opcodes)
* may be modified.
*/
public List getInstructions() {
return Arrays.asList(instrs);
public Instruction[] getInstructions() {
return instrs;
}
/**
@ -105,35 +156,45 @@ public final class Block {
return blockNr;
}
private void checkConsistent() {
/* Check if all instructions are of correct type */
private void initCode() {
int size = instrs.length;
int depth = 0;
int poppush[] = new int[2];
boolean needGoto = true;
for (int i = 0; i < size; i++) {
instrs[i].getStackPopPush(poppush);
depth += poppush[0];
if (pop < depth)
pop = depth;
depth -= poppush[1];
int opcode = instrs[i].getOpcode();
switch (opcode) {
case Opcodes.opc_goto:
throw new IllegalArgumentException("goto in block");
case Opcodes.opc_lookupswitch:
if (succs == null || succs.length == 0)
if (succs.length != instrs[i].getValues().length + 1)
throw new IllegalArgumentException
("no successors for switch");
if (i != size - 1)
throw new IllegalArgumentException
("switch in the middle!");
return;
needGoto = false;
break;
case Opcodes.opc_ret: case Opcodes.opc_athrow:
case Opcodes.opc_ireturn: case Opcodes.opc_lreturn:
case Opcodes.opc_freturn: case Opcodes.opc_dreturn:
case Opcodes.opc_areturn: case Opcodes.opc_return:
if (succs == null || succs.length > 0)
if (succs.length != 0)
throw new IllegalArgumentException
("throw or return with successor.");
if (i != size - 1)
throw new IllegalArgumentException
("return in the middle!");
return;
needGoto = false;
break;
case Opcodes.opc_ifeq: case Opcodes.opc_ifne:
case Opcodes.opc_iflt: case Opcodes.opc_ifge:
@ -144,29 +205,38 @@ public final class Block {
case Opcodes.opc_if_acmpeq: case Opcodes.opc_if_acmpne:
case Opcodes.opc_ifnull: case Opcodes.opc_ifnonnull:
case Opcodes.opc_jsr:
if (succs == null || succs.length != 2)
if (succs.length != 2)
throw new IllegalArgumentException
("successors inappropriate for if/jsr");
if (succs[0] == null && opcode == Opcodes.opc_jsr)
throw new IllegalArgumentException
("null successors inappropriate for jsr");
if (i != size - 1)
throw new IllegalArgumentException
("if/jsr in the middle!");
return;
needGoto = false;
}
}
if (succs == null || succs.length != 1)
push = pop - depth;
if (needGoto && succs.length != 1)
throw new IllegalArgumentException("no single successor block");
}
public void getStackPopPush (int[] poppush) {
poppush[0] = pop;
poppush[1] = push;
return;
}
/**
* Set the code, i.e. instructions and successor blocks.
* The instructions must be valid and match the successors.
*/
public void setCode(Collection instrs, Block[] succs) {
this.instrs = (Instruction[])
instrs.toArray(new Instruction[instrs.size()]);
public void setCode(Instruction[] instrs, Block[] succs) {
this.instrs = instrs;
this.succs = succs;
try {
checkConsistent();
initCode();
} catch (IllegalArgumentException ex) {
dumpCode(jode.GlobalOptions.err);
throw ex;

@ -228,6 +228,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
private int status = 0;
private boolean modified = false;
private boolean isGuessed = false;
private ClassPath classpath;
private int modifiers = -1;
@ -291,6 +292,14 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
* @see #load
*/
public static final int DECLARATIONS = 30;
/**
* This constant can be used as parameter to load. It specifies
* that everything in the class except debugging information and
* non-standard attributes should be loaded.
*
* @see #load
*/
public static final int NODEBUG = 80;
/**
* This constant can be used as parameter to load. It specifies
* that everything in the class except non-standard attributes
@ -574,7 +583,8 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
className = name.substring(dollar+1);
outerClass = classpath.getClassInfo(declarer.getName());
/* As mentioned above OUTERCLASS is recursive */
outerClass.loadFromReflection(declarer, OUTERCLASS);
if (outerClass.status < OUTERCLASS)
outerClass.loadFromReflection(declarer, OUTERCLASS);
} else {
/* Check if class name ends with $[numeric]$name or
* $[numeric], in which case it is a method scoped
@ -610,7 +620,6 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
interfaces = new ClassInfo[ifaces.length];
for (int i=0; i<ifaces.length; i++)
interfaces[i] = classpath.getClassInfo(ifaces[i].getName());
status |= HIERARCHY;
}
if (howMuch >= PUBLICDECLARATIONS) {
Field[] fs;
@ -670,7 +679,8 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
for (int i = is.length; --i >= 0; ) {
innerClasses[i] = classpath.getClassInfo(is[i].getName());
/* As mentioned above OUTERCLASS is loaded recursive */
innerClasses[i].loadFromReflection(is[i], OUTERCLASS);
if (innerClasses[i].status < OUTERCLASS)
innerClasses[i].loadFromReflection(is[i], OUTERCLASS);
}
} else
innerClasses = null;
@ -1002,8 +1012,11 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
throw new IllegalStateException(name);
if (status >= howMuch)
return;
if (classpath.loadClass(this, howMuch))
if (classpath.loadClass(this, howMuch)) {
if (status < howMuch)
throw new IllegalStateException("state = "+status);
return;
}
throw new FileNotFoundException(name);
}
@ -1025,16 +1038,18 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
*/
public void guess(int howMuch)
{
if (howMuch >= OUTERCLASS && status < OUTERCLASS) {
if (howMuch <= status)
throw new IllegalStateException("status = "+status);
isGuessed = true;
if (howMuch >= OUTERCLASS) {
modifiers = Modifier.PUBLIC | 0x20;
int dollar = name.lastIndexOf('$');
if (dollar == -1) {
/* normal class */
} else if (Character.isDigit(name.charAt(dollar+1))) {
/* anonymous class */
modifiers = Modifier.PUBLIC | 0x20;
methodScoped = true;
} else {
modifiers = Modifier.PUBLIC | 0x20;
className = name.substring(dollar+1);
int prevDollar = name.lastIndexOf('$', dollar);
if (prevDollar >= 0
@ -1045,22 +1060,24 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
outerClass = classpath.getClassInfo
(name.substring(0, prevDollar));
} else {
/* inner class */
modifiers = Modifier.PUBLIC | 0x20;
/* inner class, we assume it is static, so we don't
* get an exception when we search for the this$0
* parameter in an constructor invocation.
*/
modifiers |= Modifier.STATIC;
outerClass = classpath.getClassInfo
(name.substring(0, dollar));
}
}
}
if (howMuch >= HIERARCHY && status < HIERARCHY) {
modifiers = Modifier.PUBLIC | 0x20;
if (howMuch >= HIERARCHY) {
if (name.equals("java.lang.Object"))
superclass = null;
else
superclass = classpath.getClassInfo("java.lang.Object");
interfaces = new ClassInfo[0];
}
if (howMuch >= PUBLICDECLARATIONS && status < PUBLICDECLARATIONS) {
if (howMuch >= PUBLICDECLARATIONS) {
methods = new MethodInfo[0];
fields = new FieldInfo[0];
innerClasses = new ClassInfo[0];
@ -1070,7 +1087,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
/**
* This is the counter part to load. It will drop all
* informations up keep and clean up the memory.
* informations bigger than "keep" and clean up the memory.
* @param keep tells how much info we should keep, can be
* <code>NONE</code> or anything that <code>load</code> accepts.
* @see #load
@ -1080,7 +1097,7 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return;
if (modified) {
System.err.println("Dropping info between " + keep + " and "
+ status + " in modified class" + this + ".");
+ status + " in modified class " + this + ".");
Thread.dumpStack();
return;
}
@ -1101,23 +1118,21 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
methods = null;
status = keep;
} else {
if (keep < ALMOSTALL && status >= ALMOSTALL) {
for (int i=0; i < fields.length; i++)
fields[i].dropBody();
for (int i=0; i < methods.length; i++)
methods[i].dropBody();
}
if (status >= DECLARATIONS)
/* We don't drop non-public declarations, since this
* is not worth it.
*/
keep = DECLARATIONS;
for (int i=0; i < fields.length; i++)
fields[i].drop(keep);
for (int i=0; i < methods.length; i++)
methods[i].drop(keep);
}
if (keep < ALMOSTALL && status >= ALMOSTALL) {
if (keep < ALMOSTALL)
sourceFile = null;
super.dropAttributes();
}
super.drop(keep);
status = keep;
}
@ -1129,6 +1144,10 @@ public final class ClassInfo extends BinaryInfo implements Comparable {
return name;
}
public boolean isGuessed() {
return isGuessed;
}
/**
* Returns the java class name of a class, without package or
* outer classes. This is null for an anonymous class. For other

@ -156,7 +156,7 @@ public class ClassPath {
private class LocalPath extends Path {
private File dir;
private LocalPath(File path) {
public LocalPath(File path) {
dir = path;
}
@ -253,7 +253,7 @@ public class ClassPath {
} while (name.length() > 0);
}
private ZipPath(ZipFile zipfile, String prefix) {
public ZipPath(ZipFile zipfile, String prefix) {
this.file = zipfile;
this.prefix = prefix;
@ -264,7 +264,7 @@ public class ClassPath {
}
}
private ZipPath(byte[] zipcontents, String prefix)
public ZipPath(byte[] zipcontents, String prefix)
throws IOException
{
this.contents = zipcontents;
@ -354,9 +354,9 @@ public class ClassPath {
}
private class URLPath extends Path {
URL base;
private URL base;
private URLPath(URL base) {
public URLPath(URL base) {
this.base = base;
}

@ -24,27 +24,17 @@ import jode.util.StringQuoter;
* This class represents an instruction in the byte code.
*
*/
public class ConstantInstruction extends Instruction {
class ConstantInstruction extends Instruction {
/**
* The typesignature of the class/array.
*/
private Object constant;
/**
* Standard constructor: creates an opcode with parameter and
* lineNr.
*/
public ConstantInstruction(int opcode, Object constant, int lineNr) {
super(opcode, lineNr);
if (opcode != opc_ldc && opcode != opc_ldc2_w)
throw new IllegalArgumentException("Instruction has no typesig");
ConstantInstruction(int opcode, Object constant) {
super(opcode);
this.constant = constant;
}
public ConstantInstruction(int opcode, Object constant) {
this(opcode, constant, -1);
}
public final Object getConstant()
{
return constant;
@ -61,4 +51,3 @@ public class ConstantInstruction extends Instruction {
? StringQuoter.quote((String) constant) : constant);
}
}

@ -44,10 +44,10 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
this.modifier = modifier;
}
protected void readAttribute(String name, int length,
ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
void readAttribute(String name, int length,
ConstantPool cp,
DataInputStream input,
int howMuch) throws IOException {
if (howMuch >= ClassInfo.DECLARATIONS
&& name.equals("ConstantValue")) {
if (length != 2)
@ -68,19 +68,19 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
} else
super.readAttribute(name, length, cp, input, howMuch);
}
public void read(ConstantPool constantPool,
DataInputStream input, int howMuch) throws IOException {
void read(ConstantPool constantPool,
DataInputStream input, int howMuch) throws IOException {
modifier = input.readUnsignedShort();
name = constantPool.getUTF8(input.readUnsignedShort());
typeSig = constantPool.getUTF8(input.readUnsignedShort());
readAttributes(constantPool, input, howMuch);
}
public void reserveSmallConstants(GrowableConstantPool gcp) {
void reserveSmallConstants(GrowableConstantPool gcp) {
}
public void prepareWriting(GrowableConstantPool gcp) {
void prepareWriting(GrowableConstantPool gcp) {
gcp.putUTF8(name);
gcp.putUTF8(typeSig);
if (constant != null) {
@ -108,8 +108,8 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
return count;
}
public void writeKnownAttributes(GrowableConstantPool gcp,
DataOutputStream output)
void writeKnownAttributes(GrowableConstantPool gcp,
DataOutputStream output)
throws IOException {
if (constant != null) {
output.writeShort(gcp.putUTF8("ConstantValue"));
@ -132,7 +132,7 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
}
}
public void write(GrowableConstantPool constantPool,
void write(GrowableConstantPool constantPool,
DataOutputStream output) throws IOException {
output.writeShort(modifier);
output.writeShort(constantPool.putUTF8(name));
@ -140,8 +140,10 @@ public final class FieldInfo extends BinaryInfo implements Comparable {
writeAttributes(constantPool, output);
}
public void dropBody() {
super.dropAttributes();
void drop(int keep) {
if (keep < ClassInfo.DECLARATIONS)
constant = null;
super.drop(keep);
}
public String getName() {

@ -1,4 +1,4 @@
/* Handler Copyright (C) 1999 Jochen Hoenicke.
/* Handler Copyright (C) 2000 Jochen Hoenicke.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

@ -23,28 +23,18 @@ package jode.bytecode;
* This class represents an instruction in the byte code.
*
*/
public class IncInstruction extends SlotInstruction {
class IncInstruction extends SlotInstruction {
/**
* The amount of increment.
*/
private int increment;
/**
* Standard constructor: creates an opcode with parameter and
* lineNr.
*/
public IncInstruction(int opcode, int slot, int increment, int lineNr) {
super(opcode, slot, lineNr);
if (opcode != opc_iinc)
throw new IllegalArgumentException("Instruction has no increment");
this.increment = increment;
}
/**
* Creates a simple opcode, without any parameters.
*/
public IncInstruction(int opcode, int slot, int increment) {
this(opcode, slot, increment, -1);
IncInstruction(int opcode, LocalVariableInfo lvi, int increment) {
super(opcode, lvi);
this.increment = increment;
}
/**

@ -22,6 +22,20 @@ package jode.bytecode;
/**
* This class represents an instruction in the byte code.
*
* We only allow a subset of opcodes. Other opcodes are mapped to
* their simpler version. When writing the bytecode the shortest
* possible bytecode is produced.
*
* The opcodes we map are:
* <pre>
* [iflda]load_x -&gt; [iflda]load
* [iflda]store_x -&gt; [iflda]store
* [ifa]const_xx, ldc_w -&gt; ldc
* [dl]const_xx -&gt; ldc2_w
* wide opcode -&gt; opcode
* tableswitch -&gt; lookupswitch
* [a]newarray -&gt; multianewarray
* </pre>
*/
public class Instruction implements Opcodes{
/**
@ -32,80 +46,173 @@ public class Instruction implements Opcodes{
*/
private int lineAndOpcode;
/**
* Creates a new simple Instruction with no parameters. We map
* some opcodes, so you must always use the mapped opcode.
* @param opcode the opcode of this instruction.
* @exception IllegalArgumentException if opcode is not in our subset
* or if opcode needs a parameter. */
public static Instruction forOpcode(int opcode) {
switch (opcode) {
case opc_nop:
case opc_iaload: case opc_laload: case opc_faload:
case opc_daload: case opc_aaload:
case opc_baload: case opc_caload: case opc_saload:
case opc_iastore: case opc_lastore: case opc_fastore:
case opc_dastore: case opc_aastore:
case opc_bastore: case opc_castore: case opc_sastore:
case opc_pop: case opc_pop2:
case opc_dup: case opc_dup_x1: case opc_dup_x2:
case opc_dup2: case opc_dup2_x1: case opc_dup2_x2:
case opc_swap:
case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd:
case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub:
case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul:
case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv:
case opc_irem: case opc_lrem: case opc_frem: case opc_drem:
case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg:
case opc_ishl: case opc_lshl:
case opc_ishr: case opc_lshr:
case opc_iushr: case opc_lushr:
case opc_iand: case opc_land:
case opc_ior: case opc_lor:
case opc_ixor: case opc_lxor:
case opc_i2l: case opc_i2f: case opc_i2d:
case opc_l2i: case opc_l2f: case opc_l2d:
case opc_f2i: case opc_f2l: case opc_f2d:
case opc_d2i: case opc_d2l: case opc_d2f:
case opc_i2b: case opc_i2c: case opc_i2s:
case opc_lcmp: case opc_fcmpl: case opc_fcmpg:
case opc_dcmpl: case opc_dcmpg:
case opc_ireturn: case opc_lreturn:
case opc_freturn: case opc_dreturn: case opc_areturn:
case opc_return:
case opc_athrow:
case opc_arraylength:
case opc_monitorenter: case opc_monitorexit:
case opc_goto:
case opc_jsr:
case opc_ifeq: case opc_ifne:
case opc_iflt: case opc_ifge:
case opc_ifgt: case opc_ifle:
case opc_if_icmpeq: case opc_if_icmpne:
case opc_if_icmplt: case opc_if_icmpge:
case opc_if_icmpgt: case opc_if_icmple:
case opc_if_acmpeq: case opc_if_acmpne:
case opc_ifnull: case opc_ifnonnull:
return new Instruction(opcode);
default:
throw new IllegalArgumentException("Instruction has a parameter");
}
}
/**
* Creates a new ldc Instruction.
* @param opcode the opcode of this instruction.
* @param constant the constant parameter.
* @exception IllegalArgumentException if opcode is not opc_ldc or
* opc_ldc2_w.
*/
public Instruction forOpcode(int opcode, Object constant) {
if (opcode == opc_ldc || opcode == opc_ldc2_w)
return new ConstantInstruction(opcode, constant);
throw new IllegalArgumentException("Instruction has no constant");
}
/**
* Creates a new Instruction with a local variable as parameter.
* @param opcode the opcode of this instruction.
* @param lvi the local variable parameter.
* @exception IllegalArgumentException if opcode is not in our subset
* or if opcode doesn't need a single local variable as parameter.
*/
public static Instruction forOpcode(int opcode, LocalVariableInfo lvi) {
if (opcode == opc_ret
|| opcode >= opc_iload && opcode <= opc_aload
|| opcode >= opc_istore && opcode <= opc_astore)
return new SlotInstruction(opcode, lvi);
throw new IllegalArgumentException("Instruction has no slot");
}
/**
* Creates a new Instruction with reference as parameter.
* @param opcode the opcode of this instruction.
* @param reference the reference parameter.
* @exception IllegalArgumentException if opcode is not in our subset
* or if opcode doesn't need a reference as parameter.
*/
public static Instruction forOpcode(int opcode, Reference reference) {
if (opcode >= opc_getstatic && opcode <= opc_invokeinterface)
return new ReferenceInstruction(opcode, reference);
throw new IllegalArgumentException("Instruction has no reference");
}
/**
* Creates a new Instruction with type signature as parameter.
* @param opcode the opcode of this instruction.
* @param typeSig the type signature parameter.
* @exception IllegalArgumentException if opcode is not in our subset
* or if opcode doesn't need a type signature as parameter.
*/
public static Instruction forOpcode(int opcode, String typeSig) {
switch (opcode) {
case opc_new:
case opc_checkcast:
case opc_instanceof:
return new TypeInstruction(opcode, typeSig);
default:
throw new IllegalArgumentException("Instruction has no type");
}
}
// /**
// * Optional object data for this opcode. There are six different
// * usages of this field:
// * <dl>
// * <dt>opc_ldc / opc_ldc2_w</dt>
// * <dd>The constant of type Integer/Long/Float/Double/String. </dd>
// * <dt>opc_invokexxx / opc_xxxfield / opc_xxxstatic</dt>
// * <dd>The field/method Reference</dd>
// * <dt>opc_new / opc_checkcast / opc_instanceof</dt>
// * <dd>The typesignature of the class/array</dd>
// * <dt>opc_lookupswitch</dt>
// * <dd>The array of values of type int[]</dd>
// * <dt>opc_multianewarray</dt>
// * <dd>A DoubleParam: intValue contains dimension, objValue contains
// * reference </dd>
// * <dt>opc_[aildf]{load,store}</dt>
// * <dd>The LocalVariableInfo</dd>
// * <dt>opc_iinc</dt>
// * <dd>A DoubleParam: intValue contains count, objValue contains
// * local variable info.</dd>
// * </dl>
// */
// private Object param;
// /**
// * Create a new Instruction suitable for the given opcode. We map
// * some opcodes, so you must always use the mapped opcode.
// * <pre>
// * [iflda]load_x -&gt; [iflda]load
// * [iflda]store_x -&gt; [iflda]store
// * [ifa]const_xx, ldc_w -&gt; ldc
// * [dl]const_xx -&gt; ldc2_w
// * wide opcode -&gt; opcode
// * tableswitch -&gt; lookupswitch
// * [a]newarray -&gt; multianewarray
// * </pre>
// */
// public static Instruction forOpcode(int opcode) {
// if (opcode == opc_iinc)
// return new IncInstruction(opcode);
// else if (opcode == opc_ret
// || opcode >= opc_iload && opcode <= opc_aload
// || opcode >= opc_istore && opcode <= opc_astore)
// return new SlotInstruction(opcode);
// else if (opcode >= opc_getstatic && opcode <= opc_invokeinterface)
// return new ReferenceInstruction(opcode);
// else switch (opcode) {
// case opc_new:
// case opc_checkcast:
// case opc_instanceof:
// return new TypeInstruction(opcode);
// case opc_multianewarray:
// return new TypeDimensionInstruction(opcode);
// default:
// return new Instruction(opcode);
// }
// }
/**
* Creates a new switch Instruction.
* @param opcode the opcode of this instruction must be opc_lookupswitch.
* @param values an array containing the different cases.
* @exception IllegalArgumentException if opcode is not opc_lookupswitch.
*/
public static Instruction forOpcode(int opcode, int[] values) {
if (opcode == opc_lookupswitch)
return new SwitchInstruction(opcode, values);
throw new IllegalArgumentException("Instruction has no values");
}
/**
* Standard constructor: creates an opcode with parameter and
* lineNr.
* Creates a new increment Instruction.
* @param opcode the opcode of this instruction.
* @param lvi the local variable parameter.
* @param increment the increment parameter.
* @exception IllegalArgumentException if opcode is not opc_iinc.
*/
public Instruction(int opcode, int lineNr) {
if (stackDelta.charAt(opcode) == '\177')
throw new IllegalArgumentException("Unknown opcode: "+opcode);
this.lineAndOpcode = (lineNr << 8) | opcode;
public static Instruction forOpcode(int opcode,
LocalVariableInfo lvi, int increment) {
if (opcode == opc_iinc)
return new IncInstruction(opcode, lvi, increment);
throw new IllegalArgumentException("Instruction has no increment");
}
/**
* Creates a new Instruction with type signature and a dimension
* as parameter.
* @param opcode the opcode of this instruction.
* @param typeSig the type signature parameter.
* @param dimension the array dimension parameter.
* @exception IllegalArgumentException if opcode is not
* opc_multianewarray.
*/
public static Instruction forOpcode(int opcode,
String typeSig, int dimension) {
if (opcode == opc_multianewarray)
return new TypeDimensionInstruction(opcode, typeSig, dimension);
throw new IllegalArgumentException("Instruction has no dimension");
}
/**
* Creates a simple opcode, without any parameters.
*/
public Instruction(int opcode) {
this(opcode, -1);
Instruction(int opcode) {
this.lineAndOpcode = (-1 << 8) | opcode;
}
/**
@ -263,6 +370,12 @@ public class Instruction implements Opcodes{
poppush[1] = delta >> 3;
}
/**
* Gets a printable representation of the opcode with its
* parameters. This will not include the destination for jump
* instructions, since this information is not stored inside the
* instruction.
*/
public final String getDescription() {
return toString();
}
@ -276,6 +389,6 @@ public class Instruction implements Opcodes{
* \177 if opcode is illegal, or 8*stack_push + stack_pop otherwise
* The string is created by scripts/createStackDelta.pl
*/
protected final static String stackDelta =
final static String stackDelta =
"\000\010\010\010\010\010\010\010\010\020\020\010\010\010\020\020\010\010\010\010\020\010\020\010\020\010\010\010\010\010\020\020\020\020\010\010\010\010\020\020\020\020\010\010\010\010\012\022\012\022\012\012\012\012\001\002\001\002\001\001\001\001\001\002\002\002\002\001\001\001\001\002\002\002\002\001\001\001\001\003\004\003\004\003\003\003\003\001\002\021\032\043\042\053\064\022\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\011\022\011\022\012\023\012\023\012\023\012\024\012\024\012\024\000\021\011\021\012\012\022\011\021\021\012\022\012\011\011\011\014\012\012\014\014\001\001\001\001\001\001\002\002\002\002\002\002\002\002\000\000\000\001\001\001\002\001\002\001\000\100\100\100\100\100\100\100\100\177\010\011\011\011\001\011\011\001\001\177\100\001\001\000\000";
}

@ -47,7 +47,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
void readAttribute(String name, int length, ConstantPool cp,
DataInputStream input, int howMuch) throws IOException {
if (howMuch >= ClassInfo.ALMOSTALL && name.equals("Code")) {
if (howMuch >= ClassInfo.NODEBUG && name.equals("Code")) {
basicblocks = new BasicBlocks(this);
basicblocks.read(cp, input, howMuch);
} else if (howMuch >= ClassInfo.DECLARATIONS
@ -143,7 +143,7 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
}
}
public void write(GrowableConstantPool constantPool,
void write(GrowableConstantPool constantPool,
DataOutputStream output) throws IOException {
output.writeShort(modifier);
output.writeShort(constantPool.putUTF8(name));
@ -151,9 +151,14 @@ public final class MethodInfo extends BinaryInfo implements Comparable {
writeAttributes(constantPool, output);
}
public void dropBody() {
basicblocks = null;
super.dropAttributes();
void drop(int keep) {
if (keep < ClassInfo.DECLARATIONS)
exceptions = null;
if (keep < ClassInfo.NODEBUG)
basicblocks = null;
else
basicblocks.drop(keep);
super.drop(keep);
}
public String getName() {

@ -23,26 +23,12 @@ package jode.bytecode;
* This class represents an instruction that needs a reference, i.e.
* a method invocation or field access instruction.
*/
public final class ReferenceInstruction extends Instruction {
class ReferenceInstruction extends Instruction {
private Reference reference;
/**
* Standard constructor: creates an opcode with parameter and
* lineNr.
*/
public ReferenceInstruction(int opcode, Reference reference, int lineNr)
{
super(opcode, lineNr);
if (opcode < opc_getstatic || opcode > opc_invokeinterface)
throw new IllegalArgumentException("Instruction has no reference");
this.reference = reference;
}
/**
* Creates a simple opcode, without any parameters.
*/
public ReferenceInstruction(int opcode, Reference ref) {
this(opcode, ref, -1);
super(opcode);
this.reference = ref;
}
public final Reference getReference()
@ -67,8 +53,7 @@ public final class ReferenceInstruction extends Instruction {
/*{ require { poppush != null && poppush.length == 2
:: "poppush must be an array of two ints" } } */
{
Reference ref = getReference();
String typeSig = ref.getType();
String typeSig = reference.getType();
int opcode = getOpcode();
switch (opcode) {
case opc_invokevirtual:

@ -23,36 +23,14 @@ package jode.bytecode;
* This class represents an instruction in the byte code.
*
*/
public class SlotInstruction extends Instruction {
class SlotInstruction extends Instruction {
private LocalVariableInfo lvi;
/**
*/
public SlotInstruction(int opcode, LocalVariableInfo lvi, int lineNr) {
super(opcode, lineNr);
if (opcode != opc_iinc && opcode != opc_ret
&& (opcode < opc_iload || opcode > opc_aload)
&& (opcode < opc_istore || opcode > opc_astore))
throw new IllegalArgumentException("Instruction has no slot");
this.lvi = lvi;
}
/**
*/
public SlotInstruction(int opcode, int slot, int lineNr) {
this(opcode, LocalVariableInfo.getInfo(slot), lineNr);
}
/**
*/
public SlotInstruction(int opcode, LocalVariableInfo lvi) {
this(opcode, lvi, -1);
}
/**
*/
public SlotInstruction(int opcode, int slot) {
this(opcode, LocalVariableInfo.getInfo(slot), -1);
super(opcode);
this.lvi = lvi;
}
public boolean isStore() {

@ -24,7 +24,7 @@ import jode.util.StringQuoter;
* This class represents an instruction in the byte code.
*
*/
public class SwitchInstruction extends Instruction {
class SwitchInstruction extends Instruction {
/**
* The values for this switch.
*/
@ -34,20 +34,11 @@ public class SwitchInstruction extends Instruction {
* Standard constructor: creates an opcode with parameter and
* lineNr.
*/
public SwitchInstruction(int opcode, int[] values, int lineNr) {
super(opcode, lineNr);
if (opcode != opc_lookupswitch)
throw new IllegalArgumentException("Instruction is no switch");
SwitchInstruction(int opcode, int[] values) {
super(opcode);
this.values = values;
}
/**
* Creates a simple opcode, without any parameters.
*/
public SwitchInstruction(int opcode, int[] values) {
this(opcode, values, -1);
}
public final int[] getValues()
{
return values;

@ -20,32 +20,18 @@
package jode.bytecode;
/**
* This class represents an instruction in the byte code.
* This class represents an opc_multianewarray instruction.
*
*/
public class TypeDimensionInstruction extends TypeInstruction {
class TypeDimensionInstruction extends TypeInstruction {
/**
* The dimension of this multianewarray operation.
*/
private int dimension;
/**
* Standard constructor: creates an opcode with parameter and
* lineNr.
*/
public TypeDimensionInstruction(int opcode, String type, int dimension,
int lineNr) {
super(opcode, type, lineNr);
if (opcode != opc_multianewarray)
throw new IllegalArgumentException("Instruction has no dimension");
this.dimension = dimension;
}
/**
* Creates a simple opcode, without any parameters.
*/
public TypeDimensionInstruction(int opcode, String type, int dimension) {
this(opcode, type, dimension, -1);
super(opcode, type);
this.dimension = dimension;
}
/**

@ -23,29 +23,15 @@ package jode.bytecode;
* This class represents an instruction in the byte code.
*
*/
public class TypeInstruction extends Instruction {
class TypeInstruction extends Instruction {
/**
* The typesignature of the class/array.
*/
private String typeSig;
/**
* Standard constructor: creates an opcode with parameter and
* lineNr.
*/
public TypeInstruction(int opcode, String typeSig, int lineNr) {
super(opcode, lineNr);
if (opcode != opc_new && opcode != opc_checkcast
&& opcode != opc_instanceof && opcode != opc_multianewarray)
throw new IllegalArgumentException("Instruction has no typesig");
this.typeSig = typeSig;
}
/**
* Creates a simple opcode, without any parameters.
*/
public TypeInstruction(int opcode, String typeSig) {
this(opcode, typeSig, -1);
super(opcode);
this.typeSig = typeSig;
}
public final String getClazzType()

@ -68,7 +68,7 @@ You can also use this package to create and write new classes:
...
ClassPath path = new ClassPath("/usr/lib/java/lib/classes.zip");
ClassInfo clazz = path.getClassInfo("my.new.Class");
clazz.setModifiers(Modifiers.PUBLIC);
clazz.setModifiers(Modifier.PUBLIC);
clazz.setSourceFile("Class.pl");
clazz.set...
clazz.write(zipOutputStream);

Loading…
Cancel
Save