BCEL Library aktualisiert, Stackmaptable angefügt, Tests angepasst
This commit is contained in:
parent
a4ea466fe6
commit
b1d6b44fb9
Binary file not shown.
@ -10,6 +10,12 @@
|
||||
|
||||
## BCEL Patch
|
||||
https://issues.apache.org/jira/browse/BCEL-268
|
||||
* Submitting patch: https://commons.apache.org/patches.html
|
||||
### Änderungen im BCEL-Projekt
|
||||
* Neue Datei StackMapTableGen
|
||||
* Testen TODO:
|
||||
* Mittels BCELifier Code generieren lassen, welcher Methoden erstellt, die Branches enthalten
|
||||
* Dies dann dem StackMapTableGen übergeben und auf das erstellen von StackMapEntries abprüfen
|
||||
|
||||
# Literatur
|
||||
* Zu JVM allgemein: http://blog.jamesdbloom.com/JVMInternals.html
|
||||
|
12
notizen/stan/stackmaptable/StackMapTest5.java
Normal file
12
notizen/stan/stackmaptable/StackMapTest5.java
Normal file
@ -0,0 +1,12 @@
|
||||
class StackMapTest5{
|
||||
|
||||
void methode(){
|
||||
int i = 0;
|
||||
while(System.out == null){
|
||||
i+=1;
|
||||
while(true){
|
||||
String s = "2";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -95,7 +95,7 @@ public class ClassGenerator extends ClassGen{
|
||||
int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClasses");
|
||||
this.addAttribute(new InnerClasses(innerClassesUTF8,numberOfInnerClasses*8+2,innerClasses,this.getConstantPool().getConstantPool()));
|
||||
}
|
||||
|
||||
|
||||
public int addBootstrapMethod(BootstrapMethod bMethod) {
|
||||
int numberOfBootstrapMethods = 1;
|
||||
int name_index = this.getConstantPool().addUtf8("BootstrapMethods");
|
||||
|
@ -18,6 +18,7 @@ import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
||||
import org.apache.commons.bcel6.generic.Instruction;
|
||||
import org.apache.commons.bcel6.generic.InstructionList;
|
||||
import org.apache.commons.bcel6.generic.MethodGen;
|
||||
import org.apache.commons.bcel6.generic.StackMapTableGen;
|
||||
import org.apache.commons.bcel6.generic.Type;
|
||||
|
||||
import org.apache.commons.bcel6.Const;
|
||||
@ -72,36 +73,13 @@ public class MethodGenerator extends MethodGen{
|
||||
String retTypeSig = retType.getBytecodeSignature(cg, rs);
|
||||
|
||||
method.addAttribute(factory.createSignatureAttribute(paramTypesSig+retTypeSig));
|
||||
StackMap stackMap = this.generateStackMapFrame();
|
||||
|
||||
StackMap stackMap = new StackMapTableGen(this.getInstructionList(), cp).getStackMap();
|
||||
if(stackMap != null)method.addCodeAttribute(stackMap);
|
||||
|
||||
return method.getMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return null - falls kein StackMapFrame für die Methode notwendig ist
|
||||
*/
|
||||
private StackMap generateStackMapFrame(){
|
||||
int length=2; //+2 wegen NumberOfEntries
|
||||
Menge<StackMapEntry> entries = CodeHelper.getStackMapEntries(getInstructionList(), cp);
|
||||
if(entries.size()==0)return null;
|
||||
StackMapEntry[] entryArray = new StackMapEntry[entries.size()];
|
||||
for(int i = 0; i<entries.size();i++){
|
||||
entryArray[i] = entries.get(i);
|
||||
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
||||
try {
|
||||
entries.get(i).dump(new DataOutputStream(testOut));
|
||||
} catch (IOException e) {
|
||||
//Kann nicht auftreten. Es wird in Byte-Array geschrieben.
|
||||
e.printStackTrace();
|
||||
}
|
||||
length+=testOut.size();
|
||||
}
|
||||
return new StackMap(cp.addUtf8(Const.getAttributeName(Const.ATTR_STACK_MAP_TABLE))
|
||||
,length, entryArray,cp.getConstantPool());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import org.apache.commons.bcel6.generic.DSTORE;
|
||||
import org.apache.commons.bcel6.generic.GETFIELD;
|
||||
import org.apache.commons.bcel6.generic.GotoInstruction;
|
||||
import org.apache.commons.bcel6.generic.IINC;
|
||||
import org.apache.commons.bcel6.generic.INVOKEDYNAMIC;
|
||||
import org.apache.commons.bcel6.generic.INVOKEINTERFACE;
|
||||
import org.apache.commons.bcel6.generic.Instruction;
|
||||
import org.apache.commons.bcel6.generic.InstructionHandle;
|
||||
@ -25,6 +26,7 @@ import org.apache.commons.bcel6.generic.InstructionList;
|
||||
import org.apache.commons.bcel6.generic.InstructionTargeter;
|
||||
import org.apache.commons.bcel6.generic.InvokeInstruction;
|
||||
import org.apache.commons.bcel6.generic.LDC;
|
||||
import org.apache.commons.bcel6.generic.NEW;
|
||||
import org.apache.commons.bcel6.generic.ObjectType;
|
||||
import org.apache.commons.bcel6.generic.PUTFIELD;
|
||||
import org.apache.commons.bcel6.generic.ReferenceType;
|
||||
@ -130,6 +132,20 @@ class StackItemTop implements StackItem{
|
||||
return new StackMapType(Const.ITEM_Bogus,0,cp.getConstantPool());
|
||||
}
|
||||
|
||||
}
|
||||
class StackItemUninitialized implements StackItem{
|
||||
private NEW newIns;
|
||||
private InstructionHandle handle;
|
||||
public StackItemUninitialized(NEW newInstruction, InstructionHandle instructionHandle){
|
||||
newIns = newInstruction;
|
||||
handle = instructionHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackMapType getType(ConstantPoolGen cp) {
|
||||
return new StackMapType(Const.ITEM_NewObject,handle.getPosition(),cp.getConstantPool());
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
class StackItemObject implements StackItem{
|
||||
@ -138,32 +154,10 @@ class StackItemObject implements StackItem{
|
||||
}
|
||||
}
|
||||
*/
|
||||
class StackState{
|
||||
|
||||
}
|
||||
|
||||
class LocalVarState{
|
||||
|
||||
}
|
||||
|
||||
class Fields{
|
||||
|
||||
}
|
||||
|
||||
public class CodeHelper {
|
||||
|
||||
private ArrayList<Integer> outputStack = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Pushes a new type onto the output frame stack.
|
||||
*
|
||||
* @param type
|
||||
* the type that must be pushed.
|
||||
*/
|
||||
private void push(final int type) {
|
||||
outputStack.add(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generiert die StackMapEntrys zu einer gegebenen Methode
|
||||
* @param forCode
|
||||
@ -177,10 +171,9 @@ public class CodeHelper {
|
||||
Instruction[] instructions = forCode.getInstructions();
|
||||
InstructionHandle[] instructionHandles = forCode.getInstructionHandles();
|
||||
int lastPosition = 0;
|
||||
for(int i = 0; i<forCode.getLength();i++){
|
||||
Instruction ins = instructions[i];
|
||||
InstructionHandle ih = instructionHandles[i];
|
||||
getOutput(ins, state, cp);
|
||||
|
||||
for(InstructionHandle ih : forCode.getInstructionHandles()){
|
||||
getOutput(ih, state, cp);
|
||||
if(isFrameEndpoint(ih, forCode)){
|
||||
if(!state.stack.isEmpty()){
|
||||
StackMapEntry entry = generateFullFrame(ih.getPosition(),state, cp);
|
||||
@ -236,11 +229,12 @@ public class CodeHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void getOutput(Instruction ins, JVMState ret, ConstantPoolGen cp){
|
||||
static void getOutput(InstructionHandle instructionHandle, JVMState ret, ConstantPoolGen cp){
|
||||
/*
|
||||
* TODO:
|
||||
* Berechnet den Output auf den Stack und ändert den LocalVarState und den StackState je nach Instruktion ab
|
||||
*/
|
||||
Instruction ins = instructionHandle.getInstruction();
|
||||
int opcode = ins.getOpcode();
|
||||
StackItem t1,t2,t3,t4;
|
||||
switch (opcode) {
|
||||
@ -618,6 +612,7 @@ public class CodeHelper {
|
||||
case Const.INVOKESPECIAL:
|
||||
case Const.INVOKESTATIC:
|
||||
case Const.INVOKEINTERFACE:
|
||||
case Const.INVOKEDYNAMIC:
|
||||
InvokeInstruction invokeIns = (InvokeInstruction) ins;
|
||||
ret.pop(invokeIns.consumeStack(cp));
|
||||
/*
|
||||
@ -648,14 +643,12 @@ public class CodeHelper {
|
||||
ret.push(new StackItemType((ReferenceType) retType));
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case Const.INVOKEDYNAMIC:
|
||||
ret.pop(item.strVal2);
|
||||
ret.push(cw, item.strVal2);
|
||||
break;
|
||||
case Const.NEW:
|
||||
ret.push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
|
||||
NEW newIns = (NEW) ins;
|
||||
ret.push(new StackItemUninitialized(newIns, instructionHandle));
|
||||
//ret.push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
|
||||
break;
|
||||
/*
|
||||
case Const.NEWARRAY:
|
||||
ret.pop();
|
||||
switch (arg) {
|
||||
@ -712,20 +705,6 @@ public class CodeHelper {
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the action of the given instruction on the output stack frame.
|
||||
*
|
||||
* @param opcode
|
||||
* the opcode of the instruction.
|
||||
* @param arg
|
||||
* the operand of the instruction, if any.
|
||||
* @param item
|
||||
* the operand of the instructions, if any.
|
||||
*/
|
||||
void execute(Instruction ins) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
class IfElseStatement{
|
||||
class IfElseIfStatement{
|
||||
method(flag){
|
||||
if(flag){
|
||||
|
||||
return 0;
|
||||
}else if(flag){
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,6 +9,6 @@ public class IfElseIfStatementTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory+outputFile);
|
||||
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory);
|
||||
}
|
||||
}
|
||||
|
10
test/bytecode/stackmaptable/IfStatement.jav
Normal file
10
test/bytecode/stackmaptable/IfStatement.jav
Normal file
@ -0,0 +1,10 @@
|
||||
class IfStatement{
|
||||
Integer methode(Boolean b){
|
||||
if(b){
|
||||
return 1;
|
||||
}else{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
16
test/bytecode/stackmaptable/IfStatementTest.java
Normal file
16
test/bytecode/stackmaptable/IfStatementTest.java
Normal file
@ -0,0 +1,16 @@
|
||||
package bytecode.stackmaptable;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import bytecode.SingleClassTester;
|
||||
|
||||
public class IfStatementTest {
|
||||
public final static String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/stackmaptable/";
|
||||
public final static String testFile = "IfStatement.jav";
|
||||
public final static String outputFile = "IfStatement.class";
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory);
|
||||
}
|
||||
}
|
18
test/bytecode/types/OverloadingReplace.jav
Normal file
18
test/bytecode/types/OverloadingReplace.jav
Normal file
@ -0,0 +1,18 @@
|
||||
import java.util.Vector;
|
||||
|
||||
class OverloadingReplace{
|
||||
|
||||
Vector<String> test;
|
||||
|
||||
void method(){
|
||||
method(test);
|
||||
}
|
||||
|
||||
void method(Vector<String> v) {
|
||||
|
||||
}
|
||||
|
||||
void method(Vector<Integer> v) {
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user