java - 尝试通过 WALA 检测源代码时出现异常 : java. lang.ClassFormatError:StackMapTable 格式错误:属性大小错误

标签 java eclipse-plugin instrumentation soot

我有一个像这样的简单程序:

package tests;

import java.util.Scanner;

public class TestSum {

    public static void main(String[] args) {
        int sum = 0;
        System.out.print("Please enter starting i: ");
        int i = new Scanner(System.in).nextInt();
        while ( i < 11 ) {
            sum = sum + i;
            i = i + 1;
        }
        System.out.println("sum = " + sum);
        System.out.println("Ending i = " + i);
    }
}

我将其构建到一个 jar 文件中,我想使用 WALA 添加更多经过检测的源代码来计算循环执行的次数以进行动态分析。

这是我使用 Wala 所做的,大部分内容取自此示例 Wala Bench Example

import com.ibm.wala.shrikeBT.*;
import com.ibm.wala.shrikeBT.analysis.Verifier;
import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder;
import com.ibm.wala.shrikeBT.shrikeCT.ClassInstrumenter;
import com.ibm.wala.shrikeBT.shrikeCT.OfflineInstrumenter;
import com.ibm.wala.shrikeCT.ClassWriter;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintStream;
import java.io.Writer;

/**
 * Created by quocnghi on 2/2/17.
 */
public class InstrumentedTest {
    private final static boolean disasm = true;

    private final static boolean verify = true;

    private static OfflineInstrumenter instrumenter = new OfflineInstrumenter(true);

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 1; i++) {

            Writer w = new BufferedWriter(new FileWriter("report", false));

            args = instrumenter.parseStandardArgs(args);

            instrumenter.setPassUnmodifiedClasses(true);
            instrumenter.beginTraversal();
            ClassInstrumenter ci;
            while ((ci = instrumenter.nextClass()) != null) {
                doClass(ci, w);
            }
            instrumenter.close();
        }
    }

    static final String fieldName = "_Bench_enable_trace";

    // Keep these commonly used instructions around
    static final Instruction getSysOut = Util.makeGet(System.class, "out");

    static final Instruction callPrintln = Util.makeInvoke(PrintStream.class, "println", new Class[]{String.class});

    private static void doClass(final ClassInstrumenter ci, Writer w) throws Exception {
        final String className = ci.getReader().getName();
        System.out.println("Class name : " + className);
        w.write("Class: " + className + "\n");
        w.flush();

        for (int m = 0; m < ci.getReader().getMethodCount(); m++) {
            MethodData d = ci.visitMethod(m);
            System.out.println(d.getName());
            // d could be null, e.g., if the method is abstract or native
            if (d != null) {
                w.write("Instrumenting " + ci.getReader().getMethodName(m) + " " + ci.getReader().getMethodType(m) + ":\n");
                w.flush();

                if (disasm) {
                    w.write("Initial ShrikeBT code:\n");
                    (new Disassembler(d)).disassembleTo(w);
                    w.flush();
                }

                if (verify) {
                    Verifier v = new Verifier(d);
                    v.verify();
                }

                MethodEditor methodEditor = new MethodEditor(d);
                methodEditor.beginPass();

                final int noTraceLabel = methodEditor.allocateLabel();

                IInstruction[] instr = methodEditor.getInstructions();
                final String msg0 = "Loop called at " + Util.makeClass("L" + ci.getReader().getName() + ";") + "."
                        + ci.getReader().getMethodName(m);
                int i = 0;

                for (IInstruction in : instr) {
                    if (in instanceof ConditionalBranchInstruction) {

                        int b = i;
                        methodEditor.insertBefore(i, new MethodEditor.Patch() {
                            @Override
                            public void emitTo(MethodEditor.Output w) {
                                w.emit(getSysOut);
                                w.emit(ConstantInstruction.makeString(msg0));
                                w.emit(callPrintln);
                                w.emitLabel(noTraceLabel);
                            }
                        });
                    }

                    i++;
                    System.out.println(in.toString());
                }
                methodEditor.applyPatches();
                if (disasm) {
                    w.write("Final ShrikeBT code:\n");
                    (new Disassembler(d)).disassembleTo(w);
                    w.flush();
                }
            }
        }
        ClassWriter cw = ci.emitClass();
        instrumenter.outputModifiedClass(ci, cw);
    }
}

我希望添加更多检测代码后,程序应该变成这样,在循环中添加一行 System.out.println :

封装测试;

import java.util.Scanner;

public class TestSum {

    public static void main(String[] args) {
        int sum = 0;
        System.out.print("Please enter starting i: ");
        int i = new Scanner(System.in).nextInt();
        while ( i < 11 ) {
            sum = sum + i;
            i = i + 1;
            System.out.println("One count for this loop");
        }
        System.out.println("sum = " + sum);
        System.out.println("Ending i = " + i);
    }
}

但是我收到了这个错误:

java.lang.ClassFormatError: StackMapTable format error: wrong attribute size

最佳答案

瓦拉does have StackMapTable support ,但也许有些东西坏了。我建议filing an issue .

关于java - 尝试通过 WALA 检测源代码时出现异常 : java. lang.ClassFormatError:StackMapTable 格式错误:属性大小错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42004343/

相关文章:

java - 使用 XSL 获取当前页面 URL

java - 光标已关闭

java - 如何使用 IContentAssist 处理器在自动完成中显示弹出的附加信息

Maven eclipse 插件报错 Lorg/sonatype/plexus/build/incremental/BuildContext;

缺少 Javassist 依赖的 jar

java - Websocket 服务器初始化与另一个 websocket 服务器的连接

java - freemarker 宏参数内的 if-else 语句?

eclipse-plugin - ANTLR 在输入 '/' 处没有可行的替代方案

java - 如何使用 javaagent 访问工具方法的变量?

java - 插桩导致常量池损坏