package com.github.ompc.greys.core.util; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.AdviceAdapter; /** * ASM代码锁<br/> * Created by oldmanpushcart@gmail.com on 15/5/28. */ public class AsmCodeLock implements CodeLock, Opcodes { private final AdviceAdapter aa; // 锁标记 private boolean isLook; // 代码块开始特征数组 private final int[] beginCodeArray; // 代码块结束特征数组 private final int[] endCodeArray; // 代码匹配索引 private int index = 0; /** * 用ASM构建代码锁 * * @param aa ASM * @param beginCodeArray 代码块开始特征数组 * 字节码流要求不能破坏执行堆栈 * @param endCodeArray 代码块结束特征数组 * 字节码流要求不能破坏执行堆栈 */ public AsmCodeLock(AdviceAdapter aa, int[] beginCodeArray, int[] endCodeArray) { if (null == beginCodeArray || null == endCodeArray || beginCodeArray.length != endCodeArray.length) { throw new IllegalArgumentException(); } this.aa = aa; this.beginCodeArray = beginCodeArray; this.endCodeArray = endCodeArray; } @Override public void code(int code) { final int[] codes = isLock() ? endCodeArray : beginCodeArray; if (index >= codes.length) { reset(); return; } if (codes[index] != code) { reset(); return; } if (++index == codes.length) { // 翻转锁状态 isLook = !isLook; reset(); } } /* * 重置索引<br/> * 一般在代码序列判断失败时,则会对索引进行重置,冲头开始匹配特征序列 */ private void reset() { index = 0; } private void asm(int opcode) { aa.visitInsn(opcode); } /** * 锁定序列 */ private void lock() { for (int op : beginCodeArray) { asm(op); } } /* * 解锁序列 */ private void unLock() { for (int op : endCodeArray) { asm(op); } } @Override public boolean isLock() { return isLook; } @Override public void lock(Block block) { lock(); try { block.code(); } finally { unLock(); } } }