📄 classfilewriter.java
字号:
break; case ByteCode.BIPUSH: if ((byte) theOperand != theOperand) throw new IllegalArgumentException("out of range byte"); addToCodeBuffer(theOpCode); addToCodeBuffer((byte) theOperand); break; case ByteCode.SIPUSH: if ((short) theOperand != theOperand) throw new IllegalArgumentException("out of range short"); addToCodeBuffer(theOpCode); addToCodeInt16(theOperand); break; case ByteCode.NEWARRAY: if (!(0 <= theOperand && theOperand < 256)) throw new IllegalArgumentException("out of range index"); addToCodeBuffer(theOpCode); addToCodeBuffer(theOperand); break; case ByteCode.GETFIELD: case ByteCode.PUTFIELD: if (!(0 <= theOperand && theOperand < 65536)) throw new IllegalArgumentException("out of range field"); addToCodeBuffer(theOpCode); addToCodeInt16(theOperand); break; case ByteCode.LDC: case ByteCode.LDC_W: case ByteCode.LDC2_W: if (!(0 <= theOperand && theOperand < 65536)) throw new IllegalArgumentException("out of range index"); if (theOperand >= 256 || theOpCode == ByteCode.LDC_W || theOpCode == ByteCode.LDC2_W) { if (theOpCode == ByteCode.LDC) { addToCodeBuffer(ByteCode.LDC_W); } else { addToCodeBuffer(theOpCode); } addToCodeInt16(theOperand); } else { addToCodeBuffer(theOpCode); addToCodeBuffer(theOperand); } break; case ByteCode.RET: case ByteCode.ILOAD: case ByteCode.LLOAD: case ByteCode.FLOAD: case ByteCode.DLOAD: case ByteCode.ALOAD: case ByteCode.ISTORE: case ByteCode.LSTORE: case ByteCode.FSTORE: case ByteCode.DSTORE: case ByteCode.ASTORE: if (!(0 <= theOperand && theOperand < 65536)) throw new IllegalArgumentException("out of range variable"); if (theOperand >= 256) { addToCodeBuffer(ByteCode.WIDE); addToCodeBuffer(theOpCode); addToCodeInt16(theOperand); } else { addToCodeBuffer(theOpCode); addToCodeBuffer(theOperand); } break; default: throw new IllegalArgumentException( "Unexpected opcode for 1 operand"); } itsStackTop = (short) newStack; if (newStack > itsMaxStack) itsMaxStack = (short) newStack; if (DEBUGSTACK) { System.out.println("After " + bytecodeStr(theOpCode) + " stack = " + itsStackTop); } } /** * Generate the load constant bytecode for the given integer. * * @param k * the constant */ public void addLoadConstant(int k) { add(ByteCode.LDC, itsConstantPool.addConstant(k)); } /** * Generate the load constant bytecode for the given long. * * @param k * the constant */ public void addLoadConstant(long k) { add(ByteCode.LDC2_W, itsConstantPool.addConstant(k)); } /** * Generate the load constant bytecode for the given float. * * @param k * the constant */ public void addLoadConstant(float k) { add(ByteCode.LDC, itsConstantPool.addConstant(k)); } /** * Generate the load constant bytecode for the given double. * * @param k * the constant */ public void addLoadConstant(double k) { add(ByteCode.LDC2_W, itsConstantPool.addConstant(k)); } /** * Generate the load constant bytecode for the given string. * * @param k * the constant */ public void addLoadConstant(String k) { add(ByteCode.LDC, itsConstantPool.addConstant(k)); } /** * Add the given two-operand bytecode to the current method. * * @param theOpCode * the opcode of the bytecode * @param theOperand1 * the first operand of the bytecode * @param theOperand2 * the second operand of the bytecode */ public void add(int theOpCode, int theOperand1, int theOperand2) { if (DEBUGCODE) { System.out.println("Add " + bytecodeStr(theOpCode) + ", " + Integer.toHexString(theOperand1) + ", " + Integer.toHexString(theOperand2)); } int newStack = itsStackTop + stackChange(theOpCode); if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); if (theOpCode == ByteCode.IINC) { if (!(0 <= theOperand1 && theOperand1 < 65536)) throw new IllegalArgumentException("out of range variable"); if (!(0 <= theOperand2 && theOperand2 < 65536)) throw new IllegalArgumentException("out of range increment"); if (theOperand1 > 255 || theOperand2 < -128 || theOperand2 > 127) { addToCodeBuffer(ByteCode.WIDE); addToCodeBuffer(ByteCode.IINC); addToCodeInt16(theOperand1); addToCodeInt16(theOperand2); } else { addToCodeBuffer(ByteCode.WIDE); addToCodeBuffer(ByteCode.IINC); addToCodeBuffer(theOperand1); addToCodeBuffer(theOperand2); } } else if (theOpCode == ByteCode.MULTIANEWARRAY) { if (!(0 <= theOperand1 && theOperand1 < 65536)) throw new IllegalArgumentException("out of range index"); if (!(0 <= theOperand2 && theOperand2 < 256)) throw new IllegalArgumentException("out of range dimensions"); addToCodeBuffer(ByteCode.MULTIANEWARRAY); addToCodeInt16(theOperand1); addToCodeBuffer(theOperand2); } else { throw new IllegalArgumentException( "Unexpected opcode for 2 operands"); } itsStackTop = (short) newStack; if (newStack > itsMaxStack) itsMaxStack = (short) newStack; if (DEBUGSTACK) { System.out.println("After " + bytecodeStr(theOpCode) + " stack = " + itsStackTop); } } public void add(int theOpCode, String className) { if (DEBUGCODE) { System.out.println("Add " + bytecodeStr(theOpCode) + ", " + className); } int newStack = itsStackTop + stackChange(theOpCode); if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); switch (theOpCode) { case ByteCode.NEW: case ByteCode.ANEWARRAY: case ByteCode.CHECKCAST: case ByteCode.INSTANCEOF: { short classIndex = itsConstantPool.addClass(className); addToCodeBuffer(theOpCode); addToCodeInt16(classIndex); } break; default: throw new IllegalArgumentException("bad opcode for class reference"); } itsStackTop = (short) newStack; if (newStack > itsMaxStack) itsMaxStack = (short) newStack; if (DEBUGSTACK) { System.out.println("After " + bytecodeStr(theOpCode) + " stack = " + itsStackTop); } } public void add(int theOpCode, String className, String fieldName, String fieldType) { if (DEBUGCODE) { System.out.println("Add " + bytecodeStr(theOpCode) + ", " + className + ", " + fieldName + ", " + fieldType); } int newStack = itsStackTop + stackChange(theOpCode); char fieldTypeChar = fieldType.charAt(0); int fieldSize = (fieldTypeChar == 'J' || fieldTypeChar == 'D') ? 2 : 1; switch (theOpCode) { case ByteCode.GETFIELD: case ByteCode.GETSTATIC: newStack += fieldSize; break; case ByteCode.PUTSTATIC: case ByteCode.PUTFIELD: newStack -= fieldSize; break; default: throw new IllegalArgumentException("bad opcode for field reference"); } if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); short fieldRefIndex = itsConstantPool.addFieldRef(className, fieldName, fieldType); addToCodeBuffer(theOpCode); addToCodeInt16(fieldRefIndex); itsStackTop = (short) newStack; if (newStack > itsMaxStack) itsMaxStack = (short) newStack; if (DEBUGSTACK) { System.out.println("After " + bytecodeStr(theOpCode) + " stack = " + itsStackTop); } } public void addInvoke(int theOpCode, String className, String methodName, String methodType) { if (DEBUGCODE) { System.out.println("Add " + bytecodeStr(theOpCode) + ", " + className + ", " + methodName + ", " + methodType); } int parameterInfo = sizeOfParameters(methodType); int parameterCount = parameterInfo >>> 16; int stackDiff = (short) parameterInfo; int newStack = itsStackTop + stackDiff; newStack += stackChange(theOpCode); // adjusts for 'this' if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack); switch (theOpCode) { case ByteCode.INVOKEVIRTUAL: case ByteCode.INVOKESPECIAL: case ByteCode.INVOKESTATIC: case ByteCode.INVOKEINTERFACE: { addToCodeBuffer(theOpCode); if (theOpCode == ByteCode.INVOKEINTERFACE) { short ifMethodRefIndex = itsConstantPool.addInterfaceMethodRef( className, methodName, methodType); addToCodeInt16(ifMethodRefIndex); addToCodeBuffer(parameterCount + 1); addToCodeBuffer(0); } else { short methodRefIndex = itsConstantPool.addMethodRef(className, methodName, methodType); addToCodeInt16(methodRefIndex); } } break; default: throw new IllegalArgumentException( "bad opcode for method reference"); } itsStackTop = (short) newStack; if (newStack > itsMaxStack) itsMaxStack = (short) newStack; if (DEBUGSTACK) { System.out.println("After " + bytecodeStr(theOpCode) + " stack = " + itsStackTop); } } /** * Generate code to load the given integer on stack. * * @param k * the constant */ public void addPush(int k) { if ((byte) k == k) { if (k == -1) { add(ByteCode.ICONST_M1); } else if (0 <= k && k <= 5) { add((byte) (ByteCode.ICONST_0 + k)); } else { add(ByteCode.BIPUSH, (byte) k); } } else if ((short) k == k) { add(ByteCode.SIPUSH, (short) k); } else { addLoadConstant(k); } } public void addPush(boolean k) { add(k ? ByteCode.ICONST_1 : ByteCode.ICONST_0); } /** * Generate code to load the given long on stack. * * @param k * the constant */ public void addPush(long k) { int ik = (int) k; if (ik == k) { addPush(ik); add(ByteCode.I2L); } else { addLoadConstant(k); } } /** * Generate code to load the given double on stack. * * @param k * the constant */ public void addPush(double k) { if (k == 0.0) { // zero add(ByteCode.DCONST_0); if (1.0 / k < 0) { // Negative zero add(ByteCode.DNEG); } } else if (k == 1.0 || k == -1.0) { add(ByteCode.DCONST_1); if (k < 0) { add(ByteCode.DNEG); } } else { addLoadConstant(k); } } /** * Generate the code to leave on stack the given string even if the string * encoding exeeds the class file limit for single string constant * * @param k * the constant */ public void addPush(String k) { int length = k.length(); int limit = itsConstantPool.getUtfEncodingLimit(k, 0, length); if (limit == length) { addLoadConstant(k); return; } // Split string into picies fitting the UTF limit and generate code for // StringBuffer sb = new StringBuffer(length); // sb.append(loadConstant(piece_1)); // ... // sb.append(loadConstant(piece_N)); // sb.toString(); final String SB = "java/lang/StringBuffer"; add(ByteCode.NEW, SB); add(ByteCode.DUP); addPush(length); addInvoke(ByteCode.INVOKESPECIAL, SB, "<init>", "(I)V"); int cursor = 0; for (;;) { add(ByteCode.DUP); String s = k.substring(cursor, limit); addLoadConstant(s); addInvoke(ByteCode.INVOKEVIRTUAL, SB, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); add(ByteCode.POP); if (limit == length) { break; } cursor = limit; limit = itsConstantPool.getUtfEncodingLimit(k, limit, length); } addInvoke(ByteCode.INVOKEVIRTUAL, SB, "toString", "()Ljava/lang/String;"); } /** * Check if k fits limit on string constant size imposed by class file * format. * * @param k * the string constant */ public boolean isUnderStringSizeLimit(String k) { return itsConstantPool.isUnderUtfEncodingLimit(k); } /** * Store integer from stack top into the given local. * * @param local * number of local register */ public void addIStore(int local) { xop(ByteCode.ISTORE_0, ByteCode.ISTORE, local); } /** * Store long from stack top into the given local. * * @param local * number of local register */ public void addLStore(int local) { xop(ByteCode.LSTORE_0, ByteCode.LSTORE, local); } /** * Store float from stack top into the given local. * * @param local * number of local register */ public void addFStore(int local) { xop(ByteCode.FSTORE_0, ByteCode.FSTORE, local); } /** * Store double from stack top into the given local.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -