Chris Grindstaff đã viết một bài báo FindBugs, Part 2: Writing custom detectors trong đó ông mô tả làm thế nào để sử dụng BCEL thêm các quy tắc của riêng bạn. (BCEL không phải là thư viện bytecode duy nhất - nhưng nó là thư viện được sử dụng bởi FindBugs.)
Mã dưới đây phát ra bất kỳ trường hợp nào khi phương thức truy cập một phương thức hoặc trường tĩnh. Bạn có thể chạy nó trên bất kỳ loại nào thực hiện Runnable.
public class StaticInvocationFinder extends EmptyVisitor {
@Override
public void visitMethod(Method obj) {
System.out.println("==========================");
System.out.println("method:" + obj.getName());
Code code = obj.getCode();
InstructionList instructions = new InstructionList(code.getCode());
for (Instruction instruction : instructions.getInstructions()) {
// static field or method
if (Constants.INVOKESTATIC == instruction.getOpcode()) {
if (instruction instanceof InvokeInstruction) {
InvokeInstruction invokeInstruction = (InvokeInstruction) instruction;
ConstantPoolGen cpg = new ConstantPoolGen(obj
.getConstantPool());
System.out.println("static access:"
+ invokeInstruction.getMethodName(cpg));
System.out.println(" on type:"
+ invokeInstruction.getReferenceType(cpg));
}
}
}
instructions.dispose();
}
public static void main(String[] args) throws Exception {
JavaClass javaClass = Repository.lookupClass("StopThread$1");
StaticInvocationFinder visitor = new StaticInvocationFinder();
DescendingVisitor classWalker = new DescendingVisitor(javaClass,
visitor);
classWalker.visit();
}
}
Mã này phát ra như sau:
==========================
method:<init>
==========================
method:run
static access:access$0
on type:StopThread
Nó sẽ có thể để sau đó quét các loại StopThread, tìm lĩnh vực này và kiểm tra để xem nếu nó là dễ bay hơi.
Kiểm tra đồng bộ hóa là có thể, nhưng có thể gặp khó khăn do nhiều điều kiện MONITOREXIT. Đi bộ lên ngăn xếp cuộc gọi có thể khó khăn quá, nhưng sau đó đây không phải là một vấn đề tầm thường. Tuy nhiên, tôi nghĩ rằng nó sẽ tương đối dễ dàng để kiểm tra một mẫu lỗi nếu nó đã được thực hiện nhất quán.
BCEL trông có vẻ như được ghi lại và thực sự có lông cho đến khi bạn tìm thấy lớp học BCELifier. Nếu bạn chạy nó trên một lớp, nó sẽ rút ra nguồn Java về cách bạn sẽ xây dựng lớp đó trong BCEL như thế nào.Chạy nó trên StopThread cho này để tạo ra các truy cập $ 0 accessor tổng hợp:
private void createMethod_2() {
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(ACC_STATIC | ACC_SYNTHETIC, Type.BOOLEAN, Type.NO_ARGS, new String[] { }, "access$0", "StopThread", il, _cp);
InstructionHandle ih_0 = il.append(_factory.createFieldAccess("StopThread", "stopRequested", Type.BOOLEAN, Constants.GETSTATIC));
il.append(_factory.createReturn(Type.INT));
method.setMaxStack();
method.setMaxLocals();
_cg.addMethod(method.getMethod());
il.dispose();
}
FindBugs không phát hiện thấy thông báo "StopThread" ở trên. – auramo
@auramo: điều đó có thể đúng, nhưng nó kiểm tra một số điều kiện khác. Và như tôi đã nói, những công cụ này không thể dựa vào để hoàn thành. –