📄 ctbehavior.java
字号:
} catch (NotFoundException e) { throw new CannotCompileException(e); } catch (CompileError e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException(e); } } private byte[] makeSaveCode(ConstPool cp, CtClass rtype, int varNo) { Bytecode b = new Bytecode(cp, 0, 0); if (rtype == CtClass.voidType) { b.addOpcode(Opcode.ACONST_NULL); b.addAstore(varNo); return b.get(); } else { b.addStore(varNo, rtype); return b.get(); } } private byte[] makeRestoreCode(Bytecode code, ConstPool cp, CtClass rtype, int varNo) { if (rtype == CtClass.voidType) { if (code.getMaxLocals() < 1) code.setMaxLocals(1); return new byte[0]; } else { Bytecode b = new Bytecode(cp, 0, 0); b.addLoad(varNo, rtype); return b.get(); } } private void insertJSR(CodeIterator iterator, int subr, int pos, byte[] save, byte[] restore) throws BadBytecode { int gapSize = 5 + save.length + restore.length; boolean wide = subr - pos > Short.MAX_VALUE - gapSize - 4; gapSize = iterator.insertGap(pos, wide ? gapSize : gapSize - 2); iterator.write(save, pos); pos += save.length; if (wide) { iterator.writeByte(Opcode.JSR_W, pos); iterator.write32bit(subr - pos + gapSize, pos + 1); pos += 5; } else { iterator.writeByte(Opcode.JSR, pos); iterator.write16bit(subr - pos + gapSize, pos + 1); pos += 3; } iterator.write(restore, pos); } private int insertAfterHandler(boolean asFinally, Bytecode b, CtClass rtype, int returnVarNo) { if (!asFinally) return 0; int var = b.getMaxLocals(); b.incMaxLocals(1); int pc = b.currentPc(); b.addAstore(var); if (rtype.isPrimitive()) { char c = ((CtPrimitiveType)rtype).getDescriptor(); if (c == 'D') { b.addDconst(0.0); b.addDstore(returnVarNo); } else if (c == 'F') { b.addFconst(0); b.addFstore(returnVarNo); } else if (c == 'J') { b.addLconst(0); b.addLstore(returnVarNo); } else if (c != 'V') { // int, boolean, char, short, ... b.addIconst(0); b.addIstore(returnVarNo); } } else { b.addOpcode(Opcode.ACONST_NULL); b.addAstore(returnVarNo); } b.addOpcode(Opcode.JSR); int pc2 = b.currentPc(); b.addIndex(0); // correct later b.addAload(var); b.addOpcode(Opcode.ATHROW); int pc3 = b.currentPc(); b.write16bit(pc2, pc3 - pc2 + 1); return pc3 - pc; } /* -- OLD version -- public void insertAfter(String src) throws CannotCompileException { declaringClass.checkModify(); CodeAttribute ca = methodInfo.getCodeAttribute(); CodeIterator iterator = ca.iterator(); Bytecode b = new Bytecode(methodInfo.getConstPool(), ca.getMaxStack(), ca.getMaxLocals()); b.setStackDepth(ca.getMaxStack()); Javac jv = new Javac(b, declaringClass); try { jv.recordParams(getParameterTypes(), Modifier.isStatic(getModifiers())); CtClass rtype = getReturnType0(); int varNo = jv.recordReturnType(rtype, true); boolean isVoid = rtype == CtClass.voidType; if (isVoid) { b.addOpcode(Opcode.ACONST_NULL); b.addAstore(varNo); jv.compileStmnt(src); } else { b.addStore(varNo, rtype); jv.compileStmnt(src); b.addLoad(varNo, rtype); } byte[] code = b.get(); ca.setMaxStack(b.getMaxStack()); ca.setMaxLocals(b.getMaxLocals()); while (iterator.hasNext()) { int pos = iterator.next(); int c = iterator.byteAt(pos); if (c == Opcode.ARETURN || c == Opcode.IRETURN || c == Opcode.FRETURN || c == Opcode.LRETURN || c == Opcode.DRETURN || c == Opcode.RETURN) iterator.insert(pos, code); } } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (CompileError e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException(e); } } */ /** * Adds a catch clause that handles an exception thrown in the * body. The catch clause must end with a return or throw statement. * * @param src the source code representing the catch clause. * It must be a single statement or block. * @param exceptionType the type of the exception handled by the * catch clause. */ public void addCatch(String src, CtClass exceptionType) throws CannotCompileException { addCatch(src, exceptionType, "$e"); } /** * Adds a catch clause that handles an exception thrown in the * body. The catch clause must end with a return or throw statement. * * @param src the source code representing the catch clause. * It must be a single statement or block. * @param exceptionType the type of the exception handled by the * catch clause. * @param exceptionName the name of the variable containing the * caught exception, for example, * <code>$e</code>. */ public void addCatch(String src, CtClass exceptionType, String exceptionName) throws CannotCompileException { declaringClass.checkModify(); ConstPool cp = methodInfo.getConstPool(); CodeAttribute ca = methodInfo.getCodeAttribute(); CodeIterator iterator = ca.iterator(); Bytecode b = new Bytecode(cp, ca.getMaxStack(), ca.getMaxLocals()); b.setStackDepth(1); Javac jv = new Javac(b, declaringClass); try { jv.recordParams(getParameterTypes(), Modifier.isStatic(getModifiers())); int var = jv.recordVariable(exceptionType, exceptionName); b.addAstore(var); jv.compileStmnt(src); int stack = b.getMaxStack(); int locals = b.getMaxLocals(); if (stack > ca.getMaxStack()) ca.setMaxStack(stack); if (locals > ca.getMaxLocals()) ca.setMaxLocals(locals); int len = iterator.getCodeLength(); int pos = iterator.append(b.get()); ca.getExceptionTable().add(getStartPosOfBody(ca), len, len, cp.addClassInfo(exceptionType)); iterator.append(b.getExceptionTable(), pos); } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (CompileError e) { throw new CannotCompileException(e); } } /* CtConstructor overrides this method. */ int getStartPosOfBody(CodeAttribute ca) throws CannotCompileException { return 0; } /** * Inserts bytecode at the specified line in the body. * It is equivalent to: * * <br><code>insertAt(lineNum, true, src)</code> * * <br>See this method as well. * * @param lineNum the line number. The bytecode is inserted at the * beginning of the code at the line specified by this * line number. * @param src the source code representing the inserted bytecode. * It must be a single statement or block. * @return the line number at which the bytecode has been inserted. * * @see CtBehavior#insertAt(int,boolean,String) */ public int insertAt(int lineNum, String src) throws CannotCompileException { return insertAt(lineNum, true, src); } /** * Inserts bytecode at the specified line in the body. * * <p>If there is not * a statement at the specified line, the bytecode might be inserted * at the line including the first statement after that line specified. * For example, if there is only a closing brace at that line, the * bytecode would be inserted at another line below. * To know exactly where the bytecode will be inserted, call with * <code>modify</code> set to <code>false</code>. * * @param lineNum the line number. The bytecode is inserted at the * beginning of the code at the line specified by this * line number. * @param modify if false, this method does not insert the bytecode. * It instead only returns the line number at which * the bytecode would be inserted. * @param src the source code representing the inserted bytecode. * It must be a single statement or block. * If modify is false, the value of src can be null. * @return the line number at which the bytecode has been inserted. */ public int insertAt(int lineNum, boolean modify, String src) throws CannotCompileException { CodeAttribute ca = methodInfo.getCodeAttribute(); if (ca == null) throw new CannotCompileException("no method body"); LineNumberAttribute ainfo = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag); if (ainfo == null) throw new CannotCompileException("no line number info"); LineNumberAttribute.Pc pc = ainfo.toNearPc(lineNum); lineNum = pc.line; int index = pc.index; if (!modify) return lineNum; declaringClass.checkModify(); CodeIterator iterator = ca.iterator(); Javac jv = new Javac(declaringClass); try { jv.recordLocalVariables(ca, index); jv.recordParams(getParameterTypes(), Modifier.isStatic(getModifiers())); jv.setMaxLocals(ca.getMaxLocals()); jv.compileStmnt(src); Bytecode b = jv.getBytecode(); int locals = b.getMaxLocals(); int stack = b.getMaxStack(); ca.setMaxLocals(locals); /* We assume that there is no values in the operand stack * at the position where the bytecode is inserted. */ if (stack > ca.getMaxStack()) ca.setMaxStack(stack); iterator.insert(index, b.get()); iterator.insert(b.getExceptionTable(), index); return lineNum; } catch (NotFoundException e) { throw new CannotCompileException(e); } catch (CompileError e) { throw new CannotCompileException(e); } catch (BadBytecode e) { throw new CannotCompileException(e); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -