下面列出了怎么用org.objectweb.asm.tree.analysis.AnalyzerException的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public BasicValue binaryOperation(final AbstractInsnNode insn,
final BasicValue value1, final BasicValue value2) throws AnalyzerException {
/*
* We're looking for the assignment of a local holder objectref to a member variable.
* If we spot that, then the local holder can't be replaced, since we don't (yet)
* have the mechanics to replace the member variable with the holder's members or
* to assign all of them when this happens.
*/
if (insn.getOpcode() == Opcodes.PUTFIELD) {
if (value2.isReference() && (value1 instanceof ReplacingBasicValue)) {
final ReplacingBasicValue possibleThis = (ReplacingBasicValue) value1;
if (possibleThis.isThis() && (value2 instanceof ReplacingBasicValue)) {
// if this is a reference for a holder class, we can't replace it
if (HOLDERS.get(value2.getType().getDescriptor()) != null) {
final ReplacingBasicValue localRef = (ReplacingBasicValue) value2;
localRef.setAssignedToMember();
}
}
}
}
return super.binaryOperation(insn, value1, value2);
}
@Override
public BasicValue naryOperation(final AbstractInsnNode insn,
final List<? extends BasicValue> values) throws AnalyzerException {
if (insn instanceof MethodInsnNode) {
boolean skipOne = insn.getOpcode() != Opcodes.INVOKESTATIC;
// Note if the argument is a holder, and is used as a function argument
for(BasicValue value : values) {
// if non-static method, skip over the receiver
if (skipOne) {
skipOne = false;
continue;
}
if (value instanceof ReplacingBasicValue) {
final ReplacingBasicValue argument = (ReplacingBasicValue) value;
argument.setFunctionArgument();
}
}
}
return super.naryOperation(insn, values);
}
private void processClass(ClassWrapper classWrapper, AtomicInteger counter) {
new ArrayList<>(classWrapper.getMethods()).stream()
.filter(methodWrapper -> !excluded(methodWrapper))
.filter(methodWrapper -> !"<init>".equals(methodWrapper.getMethodNode().name))
.forEach(methodWrapper -> {
EjectorContext ejectorContext = new EjectorContext(counter, classWrapper, junkArguments, junkArgumentStrength);
getPhases(ejectorContext).forEach(ejectPhase -> {
ConstantAnalyzer constantAnalyzer = new ConstantAnalyzer();
try {
Main.info("Analyze: " + classWrapper.getOriginalName() + "::" + methodWrapper.getOriginalName() + methodWrapper.getOriginalDescription());
Frame<AbstractValue>[] frames = constantAnalyzer.analyze(classWrapper.getName(), methodWrapper.getMethodNode());
ejectPhase.process(methodWrapper, frames);
} catch (AnalyzerException e) {
Main.severe("Can't analyze method: " + classWrapper.getOriginalName() + "::" + methodWrapper.getOriginalName() + methodWrapper.getOriginalDescription());
Main.severe(e.toString());
}
});
});
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void removeDeadCode(ClassNode cn, MethodNode mn) {
Analyzer analyzer = new Analyzer(new BasicInterpreter());
try {
analyzer.analyze(cn.name, mn);
} catch (AnalyzerException e) {
ErrorDisplay.error("Could not analyze the code: " + e.getMessage());
return;
}
Frame[] frames = analyzer.getFrames();
AbstractInsnNode[] insns = mn.instructions.toArray();
for (int i = 0; i < frames.length; i++) {
AbstractInsnNode insn = insns[i];
if (frames[i] == null && insn.getType() != AbstractInsnNode.LABEL) {
mn.instructions.remove(insn);
insns[i] = null;
}
}
}
@Override
public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
if (insn.getOpcode() == Opcodes.NEW) {
final TypeInsnNode t = (TypeInsnNode) insn;
// if this is for a holder class, we'll replace it
final ValueHolderIden iden = HOLDERS.get(t.desc);
if (iden != null) {
return ReplacingBasicValue.create(Type.getObjectType(t.desc), iden, index++, valueList);
}
}
return super.newOperation(insn);
}
@Override
public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
throws AnalyzerException {
/*
* We're looking for the assignment of an operator member variable that's a holder to a local
* objectref. If we spot that, we can't replace the local objectref (at least not
* until we do the work to replace member variable holders).
*
* Note that a GETFIELD does not call newValue(), as would happen for a local variable, so we're
* emulating that here.
*/
if ((insn.getOpcode() == Opcodes.GETFIELD) && (value instanceof ReplacingBasicValue)) {
final ReplacingBasicValue possibleThis = (ReplacingBasicValue) value;
if (possibleThis.isThis()) {
final FieldInsnNode fieldInsn = (FieldInsnNode) insn;
if (HOLDERS.get(fieldInsn.desc) != null) {
final BasicValue fetchedField = super.unaryOperation(insn, value);
final ReplacingBasicValue replacingValue =
ReplacingBasicValue.create(fetchedField.getType(), null, -1, valueList);
replacingValue.setAssignedToMember();
return replacingValue;
}
}
}
return super.unaryOperation(insn, value);
}
@Override
public CoffeeValue naryOperation(final AbstractInsnNode insn, final List<? extends CoffeeValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
} else if (opcode == INVOKEDYNAMIC) {
return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
} else {
return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
}
/**
* Checks the given class.
*
* @param classReader the class to be checked.
* @param loader a <code>ClassLoader</code> which will be used to load referenced classes. May be
* {@literal null}.
* @param printResults whether to print the results of the bytecode verification.
* @param printWriter where the results (or the stack trace in case of error) must be printed.
*/
public static void verify(
final ClassReader classReader,
final ClassLoader loader,
final boolean printResults,
final PrintWriter printWriter) {
ClassNode classNode = new ClassNode();
classReader.accept(
new CheckClassAdapter(Opcodes.ASM7, classNode, false) {}, ClassReader.SKIP_DEBUG);
Type syperType = classNode.superName == null ? null : Type.getObjectType(classNode.superName);
List<MethodNode> methods = classNode.methods;
List<Type> interfaces = new ArrayList<>();
for (String interfaceName : classNode.interfaces) {
interfaces.add(Type.getObjectType(interfaceName));
}
for (MethodNode method : methods) {
SimpleVerifier verifier =
new SimpleVerifier(
Type.getObjectType(classNode.name),
syperType,
interfaces,
(classNode.access & Opcodes.ACC_INTERFACE) != 0);
Analyzer<BasicValue> analyzer = new Analyzer<>(verifier);
if (loader != null) {
verifier.setClassLoader(loader);
}
try {
analyzer.analyze(classNode.name, method);
} catch (AnalyzerException e) {
e.printStackTrace(printWriter);
}
if (printResults) {
printAnalyzerResult(method, analyzer, printWriter);
}
}
printWriter.flush();
}
public static StackFrame[] getFrames(MethodNode mn) {
InsnAnalyzer a = new InsnAnalyzer(new StackHelper());
StackFrame[] sfs = null;
try {
sfs = a.analyze(mn.owner, mn);
} catch (AnalyzerException e) {
//e.printStackTrace();
}
return sfs;
}
@Override
public ThisValue copyOperation(AbstractInsnNode insn, ThisValue value) throws AnalyzerException {
// We are just moving the value around so it maintains is this/not_this state.
boolean isThis = value.isThis;
BasicValue basic = this.underlying.copyOperation(insn, value.underlying);
return isThis
? ThisValue.createThis(basic)
: ThisValue.createNotThis(basic);
}
@Override
public ThisValue unaryOperation(AbstractInsnNode insn, ThisValue value) throws AnalyzerException {
// These create a different result (possibly null), so isn't this.
BasicValue basic = this.underlying.unaryOperation(insn, value.underlying);
return (null != basic)
? ThisValue.createNotThis(basic)
: null;
}
@Override
public ThisValue binaryOperation(AbstractInsnNode insn, ThisValue value1, ThisValue value2) throws AnalyzerException {
// These create a different result (possibly null), so isn't this.
BasicValue basic = this.underlying.binaryOperation(insn, value1.underlying, value2.underlying);
return (null != basic)
? ThisValue.createNotThis(basic)
: null;
}
@Override
public ThisValue ternaryOperation(AbstractInsnNode insn, ThisValue value1, ThisValue value2, ThisValue value3) throws AnalyzerException {
// These create a different result (possibly null), so isn't this.
BasicValue basic = this.underlying.ternaryOperation(insn, value1.underlying, value2.underlying, value3.underlying);
return (null != basic)
? ThisValue.createNotThis(basic)
: null;
}
@Override
public ThisValue naryOperation(AbstractInsnNode insn, List<? extends ThisValue> values) throws AnalyzerException {
// A new type is created, so definitely not this.
List<BasicValue> basics = values.stream().map((value) -> value.underlying).collect(Collectors.toList());
BasicValue basic = this.underlying.naryOperation(insn, basics);
return (null != basic)
? ThisValue.createNotThis(basic)
: null;
}
@Override
public BasicValue binaryOperation(final AbstractInsnNode insn,
final BasicValue value1, final BasicValue value2)
throws AnalyzerException
{
if(insn.getOpcode() == Opcodes.AALOAD)
return new BasicValue(value1.getType().getElementType());
return super.binaryOperation(insn, value1, value2);
}
/**
* Checks the given class.
*
* @param classReader the class to be checked.
* @param loader a <code>ClassLoader</code> which will be used to load referenced classes. May be
* {@literal null}.
* @param printResults whether to print the results of the bytecode verification.
* @param printWriter where the results (or the stack trace in case of error) must be printed.
*/
public static void verify(
final ClassReader classReader,
final ClassLoader loader,
final boolean printResults,
final PrintWriter printWriter) {
ClassNode classNode = new ClassNode();
classReader.accept(
new CheckClassAdapter(Opcodes.ASM7, classNode, false) {}, ClassReader.SKIP_DEBUG);
Type syperType = classNode.superName == null ? null : Type.getObjectType(classNode.superName);
List<MethodNode> methods = classNode.methods;
List<Type> interfaces = new ArrayList<Type>();
for (String interfaceName : classNode.interfaces) {
interfaces.add(Type.getObjectType(interfaceName));
}
for (MethodNode method : methods) {
SimpleVerifier verifier =
new SimpleVerifier(
Type.getObjectType(classNode.name),
syperType,
interfaces,
(classNode.access & Opcodes.ACC_INTERFACE) != 0);
Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(verifier);
if (loader != null) {
verifier.setClassLoader(loader);
}
try {
analyzer.analyze(classNode.name, method);
} catch (AnalyzerException e) {
e.printStackTrace(printWriter);
}
if (printResults) {
printAnalyzerResult(method, analyzer, printWriter);
}
}
printWriter.flush();
}
/**
* Checks the given class.
*
* @param classReader the class to be checked.
* @param loader a <code>ClassLoader</code> which will be used to load referenced classes. May be
* {@literal null}.
* @param printResults whether to print the results of the bytecode verification.
* @param printWriter where the results (or the stack trace in case of error) must be printed.
*/
public static void verify(
final ClassReader classReader,
final ClassLoader loader,
final boolean printResults,
final PrintWriter printWriter) {
ClassNode classNode = new ClassNode();
classReader.accept(
new CheckClassAdapter(Opcodes.ASM7, classNode, false) {}, ClassReader.SKIP_DEBUG);
Type syperType = classNode.superName == null ? null : Type.getObjectType(classNode.superName);
List<MethodNode> methods = classNode.methods;
List<Type> interfaces = new ArrayList<Type>();
for (String interfaceName : classNode.interfaces) {
interfaces.add(Type.getObjectType(interfaceName));
}
for (MethodNode method : methods) {
SimpleVerifier verifier =
new SimpleVerifier(
Type.getObjectType(classNode.name),
syperType,
interfaces,
(classNode.access & Opcodes.ACC_INTERFACE) != 0);
Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(verifier);
if (loader != null) {
verifier.setClassLoader(loader);
}
try {
analyzer.analyze(classNode.name, method);
} catch (AnalyzerException e) {
e.printStackTrace(printWriter);
}
if (printResults) {
printAnalyzerResult(method, analyzer, printWriter);
}
}
printWriter.flush();
}
@Override
public void execute(AbstractInsnNode insn, Interpreter interpreter) throws AnalyzerException {
boolean never = false;
if (never) {
super.execute(insn, interpreter);
return;
}
int insnOpcode = insn.getOpcode();
if (insnOpcode == Opcodes.MONITORENTER || insnOpcode == Opcodes.MONITOREXIT) {
Value pop = pop();
interpreter.unaryOperation(insn, pop);
int local = -1;
for (int i = 0; i < getLocals(); i++) {
if (getLocal(i) == pop) local = i;
}
if (local > -1) {
if (insnOpcode == Opcodes.MONITORENTER) {
monitorEnter(local);
} else {
monitorExit(local);
}
}
} else {
super.execute(insn, interpreter);
}
}
@Override
public void visitEnd() {
checkCallSites();
if (instructions.size() == 0 || labels.size() == 0) {
accept(mv);
return;
}
this.stackRecorderVar = maxLocals;
try {
moveNew();
analyzer = new Analyzer(new FastClassVerifier(classHierarchy)) {
@Override
protected Frame newFrame(int nLocals, int nStack) {
return new MonitoringFrame(nLocals, nStack);
}
@Override
protected Frame newFrame(Frame src) {
return new MonitoringFrame(src);
}
};
analyzer.analyze(className, this);
accept(new ContinuableMethodVisitor(this));
} catch (AnalyzerException ex) {
throw new RuntimeException(ex);
}
}
@Override
public void execute(AbstractInsnNode insn, Interpreter interpreter) throws AnalyzerException {
boolean never = false;
if (never) {
super.execute(insn, interpreter);
return;
}
int insnOpcode = insn.getOpcode();
if (insnOpcode == Opcodes.MONITORENTER || insnOpcode == Opcodes.MONITOREXIT) {
Value pop = pop();
interpreter.unaryOperation(insn, pop);
int local = -1;
for (int i = 0; i < getLocals(); i++) {
if (getLocal(i) == pop) local = i;
}
if (local > -1) {
if (insnOpcode == Opcodes.MONITORENTER) {
monitorEnter(local);
} else {
monitorExit(local);
}
}
} else {
super.execute(insn, interpreter);
}
}
@Override
public void visitEnd() {
if (instructions.size() == 0 || labels.size() == 0) {
accept(mv);
return;
}
this.stackRecorderVar = maxLocals;
try {
moveNew();
analyzer = new Analyzer(new FastClassVerifier(classHierarchy)) {
@Override
protected Frame newFrame(int nLocals, int nStack) {
return new MonitoringFrame(nLocals, nStack);
}
@Override
protected Frame newFrame(Frame src) {
return new MonitoringFrame(src);
}
};
analyzer.analyze(className, this);
accept(new ContinuableMethodVisitor(this));
} catch (AnalyzerException ex) {
throw new RuntimeException(ex);
}
}
@Override
public void execute(AbstractInsnNode insn, Interpreter interpreter) throws AnalyzerException {
boolean never = false;
if (never) {
super.execute(insn, interpreter);
return;
}
int insnOpcode = insn.getOpcode();
if (insnOpcode == Opcodes.MONITORENTER || insnOpcode == Opcodes.MONITOREXIT) {
Value pop = pop();
interpreter.unaryOperation(insn, pop);
int local = -1;
for (int i = 0; i < getLocals(); i++) {
if (getLocal(i) == pop) local = i;
}
if (local > -1) {
if (insnOpcode == Opcodes.MONITORENTER) {
monitorEnter(local);
} else {
monitorExit(local);
}
}
} else {
super.execute(insn, interpreter);
}
}
@Override
public void visitEnd() {
if (instructions.size() == 0 || labels.size() == 0) {
accept(mv);
return;
}
this.stackRecorderVar = maxLocals;
try {
moveNew();
analyzer = new Analyzer(new FastClassVerifier(classHierarchy)) {
@Override
protected Frame newFrame(int nLocals, int nStack) {
return new MonitoringFrame(nLocals, nStack);
}
@Override
protected Frame newFrame(Frame src) {
return new MonitoringFrame(src);
}
};
analyzer.analyze(className, this);
accept(new ContinuableMethodVisitor(this));
} catch (AnalyzerException ex) {
throw new RuntimeException(ex);
}
}
/**
* Find the instruction which pops the value pushed by the specified
* instruction
*
* @param target target method
* @param node push node
* @return pop instruction or null if not found
*/
public AbstractInsnNode findPopInsn(Target target, AbstractInsnNode node) {
try {
new PopAnalyzer(node).analyze(target.classNode.name, target.method);
} catch (AnalyzerException ex) {
if (ex.getCause() instanceof AnalysisResultException) {
return ((AnalysisResultException)ex.getCause()).getResult();
}
InsnFinder.logger.catching(ex);
}
return null;
}
@Override
public BasicValue copyOperation(final AbstractInsnNode insn,
final BasicValue value)
throws AnalyzerException
{
return createNode(insn, super.copyOperation(insn, value), value);
}
@Override
public BasicValue unaryOperation(final AbstractInsnNode insn,
final BasicValue value)
throws AnalyzerException
{
return createNode(insn, super.unaryOperation(insn, null), value);
}
@Override
public BasicValue binaryOperation(final AbstractInsnNode insn,
final BasicValue value1, final BasicValue value2)
throws AnalyzerException
{
return createNode(insn, super.binaryOperation(insn, null, null), value1,
value2);
}
@Override
public BasicValue ternaryOperation(final AbstractInsnNode insn,
final BasicValue v1, final BasicValue v2, final BasicValue v3)
throws AnalyzerException
{
// this method is only called for xASTORE instructions, parameter v1 is
// the value corresponding to the NEWARRAY, ANEWARRAY or MULTIANEWARRAY
// instruction having created the array, we need to insert a special
// dependency edge from the array creator to this xSTORE instruction
additionalEdges.add(new Edge(insn, findArrayCreatorPredecessor(v1)));
return createNode(insn, super.ternaryOperation(insn, null, null, null),
v1, v2, v3);
}
@Override
public BasicValue naryOperation(final AbstractInsnNode insn,
final List<? extends BasicValue> values)
throws AnalyzerException
{
return createNode(insn, super.naryOperation(insn, null),
(BasicValue[]) values.toArray(new BasicValue[values.size()]));
}
@Override
public void returnOperation(final AbstractInsnNode insn,
final BasicValue value, final BasicValue expected)
throws AnalyzerException
{
Preconditions.checkState(insn.getOpcode() == ARETURN);
Preconditions.checkState(unwrap(value).getType().equals(
Type.getType(Rule.class)));
Preconditions.checkState(unwrap(expected).getType().equals(
Type.getType(Rule.class)));
Preconditions.checkState(method.getReturnInstructionNode() == null);
method.setReturnInstructionNode(createNode(insn, null, value));
}