📄 expreditor.java
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */package javassist.expr;import javassist.bytecode.*;import javassist.CtClass;import javassist.CannotCompileException;/** * A translator of method bodies. * * <p>The users can define a subclass of this class to customize how to * modify a method body. The overall architecture is similar to the * strategy pattern. * * <p>If <code>instrument()</code> is called in * <code>CtMethod</code>, the method body is scanned from the beginning * to the end. * Whenever an expression, such as a method call and a <tt>new</tt> * expression (object creation), * is found, <code>edit()</code> is called in <code>ExprEdit</code>. * <code>edit()</code> can inspect and modify the given expression. * The modification is reflected on the original method body. If * <code>edit()</code> does nothing, the original method body is not * changed. * * <p>The following code is an example: * * <ul><pre> * CtMethod cm = ...; * cm.instrument(new ExprEditor() { * public void edit(MethodCall m) throws CannotCompileException { * if (m.getClassName().equals("Point")) { * System.out.println(m.getMethodName() + " line: " * + m.getLineNumber()); * } * }); * </pre></ul> * * <p>This code inspects all method calls appearing in the method represented * by <code>cm</code> and it prints the names and the line numbers of the * methods declared in class <code>Point</code>. This code does not modify * the body of the method represented by <code>cm</code>. If the method * body must be modified, call <code>replace()</code> * in <code>MethodCall</code>. * * @see javassist.CtClass#instrument(ExprEditor) * @see javassist.CtMethod#instrument(ExprEditor) * @see javassist.CtConstructor#instrument(ExprEditor) * @see MethodCall * @see NewExpr * @see FieldAccess * * @see javassist.CodeConverter */public class ExprEditor { /** * Default constructor. It does nothing. */ public ExprEditor() {} static class NewOp { NewOp next; int pos; String type; NewOp(NewOp n, int p, String t) { next = n; pos = p; type = t; } } /** * Undocumented method. Do not use; internal-use only. */ public boolean doit(CtClass clazz, MethodInfo minfo) throws CannotCompileException { CodeAttribute codeAttr = minfo.getCodeAttribute(); if (codeAttr == null) return false; CodeIterator iterator = codeAttr.iterator(); boolean edited = false; int maxLocals = codeAttr.getMaxLocals(); int maxStack = 0; NewOp newList = null; ConstPool cp = minfo.getConstPool(); int prevOp = Opcode.NOP; while (iterator.hasNext()) try { Expr expr = null; int pos = iterator.next(); int c = iterator.byteAt(pos); if (c == Opcode.INVOKESTATIC || c == Opcode.INVOKEINTERFACE || c == Opcode.INVOKEVIRTUAL) { expr = new MethodCall(pos, iterator, clazz, minfo); edit((MethodCall)expr); } else if (c == Opcode.GETFIELD || c == Opcode.GETSTATIC || c == Opcode.PUTFIELD || c == Opcode.PUTSTATIC) { expr = new FieldAccess(pos, iterator, clazz, minfo, c, prevOp); edit((FieldAccess)expr); } else if (c == Opcode.NEW) { int index = iterator.u16bitAt(pos + 1); newList = new NewOp(newList, pos, cp.getClassInfo(index)); } else if (c == Opcode.INVOKESPECIAL) { if (newList != null && cp.isConstructor(newList.type, iterator.u16bitAt(pos + 1)) > 0) { expr = new NewExpr(pos, iterator, clazz, minfo, newList.type, newList.pos); edit((NewExpr)expr); newList = newList.next; } else { expr = new MethodCall(pos, iterator, clazz, minfo); MethodCall mcall = (MethodCall)expr; if (!mcall.getMethodName().equals( MethodInfo.nameInit)) edit(mcall); } } else if (c == Opcode.INSTANCEOF) { expr = new Instanceof(pos, iterator, clazz, minfo); edit((Instanceof)expr); } else if (c == Opcode.CHECKCAST) { expr = new Cast(pos, iterator, clazz, minfo); edit((Cast)expr); } prevOp = c; if (expr != null && expr.edited()) { edited = true; maxLocals = max(maxLocals, expr.locals()); maxStack = max(maxStack, expr.stack()); } } catch (BadBytecode e) { throw new CannotCompileException(e); } ExceptionTable et = codeAttr.getExceptionTable(); int n = et.size(); for (int i = 0; i < n; ++i) { Handler h = new Handler(et, i, iterator, clazz, minfo); edit(h); if (h.edited()) { edited = true; maxLocals = max(maxLocals, h.locals()); maxStack = max(maxStack, h.stack()); } } codeAttr.setMaxLocals(maxLocals); codeAttr.setMaxStack(codeAttr.getMaxStack() + maxStack); return edited; } private int max(int i, int j) { return i > j ? i : j; } /** * Edits a <tt>new</tt> expression (overridable). * The default implementation performs nothing. * * @param e the <tt>new</tt> expression creating an object. */ public void edit(NewExpr e) throws CannotCompileException {} /** * Edits a method call (overridable). * The default implementation performs nothing. */ public void edit(MethodCall m) throws CannotCompileException {} /** * Edits a field-access expression (overridable). * Field access means both read and write. * The default implementation performs nothing. */ public void edit(FieldAccess f) throws CannotCompileException {} /** * Edits an instanceof expression (overridable). * The default implementation performs nothing. */ public void edit(Instanceof i) throws CannotCompileException {} /** * Edits an expression for explicit type casting (overridable). * The default implementation performs nothing. */ public void edit(Cast c) throws CannotCompileException {} /** * Edits a catch clause (overridable). * The default implementation performs nothing. */ public void edit(Handler h) throws CannotCompileException {}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -