📄 codeattrinfoeditor.java
字号:
} // Implementations for ExceptionInfoVisitor. public void visitExceptionInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, ExceptionInfo exceptionInfo) { // Remap the code offsets. Note that the instruction offset map also has // an entry for the first offset after the code, for u2endpc. exceptionInfo.u2startpc = remapInstructionOffset(exceptionInfo.u2startpc); exceptionInfo.u2endpc = remapInstructionOffset(exceptionInfo.u2endpc); exceptionInfo.u2handlerpc = remapInstructionOffset(exceptionInfo.u2handlerpc); } // Implementations for LineNumberInfoVisitor. public void visitLineNumberInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, LineNumberInfo lineNumberInfo) { // Remap the code offset. lineNumberInfo.u2startpc = remapInstructionOffset(lineNumberInfo.u2startpc); } // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, LocalVariableInfo localVariableInfo) { // Remap the code offset and length. localVariableInfo.u2length = remapBranchOffset(localVariableInfo.u2startpc, localVariableInfo.u2length); localVariableInfo.u2startpc = remapInstructionOffset(localVariableInfo.u2startpc); } // Implementations for LocalVariableTypeInfoVisitor. public void visitLocalVariableTypeInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, LocalVariableTypeInfo localVariableTypeInfo) { // Remap the code offset and length. localVariableTypeInfo.u2length = remapBranchOffset(localVariableTypeInfo.u2startpc, localVariableTypeInfo.u2length); localVariableTypeInfo.u2startpc = remapInstructionOffset(localVariableTypeInfo.u2startpc); } // Small utility methods. /** * Modifies the given code based on the previously specified changes. * * @param classFile the class file of the code to be changed. * @param methodInfo the method of the code to be changed. * @param codeAttrInfo the code to be changed. * @return the new code length. */ private int moveInstructions(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo) { byte[] oldCode = codeAttrInfo.code; int oldLength = codeAttrInfo.u4codeLength; // Make sure there is a sufficiently large instruction offset map. if (instructionOffsetMap == null || instructionOffsetMap.length < oldLength + 1) { instructionOffsetMap = new int[oldLength + 1]; } // Fill out the offset map that specifies the new instruction offsets, // given their current instruction offsets, by going over the // instructions, deleting and inserting instructions as specified. int oldOffset = 0; int newOffset = 0; boolean lengthIncreased = false; do { // Get the next instruction. Instruction instruction = InstructionFactory.create(oldCode, oldOffset); // Compute the mapping of the instruction. newOffset = mapInstruction(instruction, oldOffset, newOffset); oldOffset += instruction.length(oldOffset); // Is the new instruction exceeding the available space? if (newOffset > oldOffset) { // Remember to create a new code array later on. lengthIncreased = true; } } while (oldOffset < oldLength); // Also add an entry for the first offset after the code. instructionOffsetMap[oldOffset] = newOffset; // Create a new code array if necessary. if (lengthIncreased) { codeAttrInfo.code = new byte[newOffset]; } // Now actually move the instructions based on this map. oldOffset = 0; do { // Get the next instruction. Instruction instruction = InstructionFactory.create(oldCode, oldOffset); // Move the instruction to its new offset. moveInstruction(classFile, methodInfo, codeAttrInfo, oldOffset, instruction); oldOffset += instruction.length(oldOffset); } while (oldOffset < oldLength); return newOffset; } /** * Fills out the instruction offset map for the given instruction with its * new offset. * @param instruction the instruction to be moved. * @param oldOffset the instruction's old offset. * @param newOffset the instruction's new offset. * @return the next new offset. */ private int mapInstruction(Instruction instruction, int oldOffset, int newOffset) { instructionOffsetMap[oldOffset] = newOffset; // Account for the pre-inserted instruction, if any. Instruction preInstruction = preInsertions[oldOffset]; if (preInstruction != null) { newOffset += preInstruction.length(newOffset); } // Account for the current instruction, if it shouldn't be deleted. if (!deleted[oldOffset] ) { // Note that the instruction's length may change at its new offset, // e.g. if it is a switch instruction. newOffset += instruction.length(newOffset); } // Account for the post-inserted instruction, if any. Instruction postInstruction = postInsertions[oldOffset]; if (postInstruction != null) { newOffset += postInstruction.length(newOffset); } return newOffset; } /** * Moves the given instruction to its new offset. */ private void moveInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int oldOffset, Instruction instruction) { int newOffset = remapInstructionOffset(oldOffset); // Remap and insert the pre-inserted instruction, if any. Instruction preInstruction = preInsertions[oldOffset]; if (preInstruction != null) { preInstruction.accept(classFile, methodInfo, codeAttrInfo, oldOffset, this); preInstruction.write(codeAttrInfo, newOffset); newOffset += preInstruction.length(newOffset); } // Remap and insert the current instruction, if it shouldn't be deleted. if (!deleted[oldOffset]) { instruction.accept(classFile, methodInfo, codeAttrInfo, oldOffset, this); instruction.write(codeAttrInfo, newOffset); newOffset += instruction.length(newOffset); } // Remap and insert the post-inserted instruction, if any. Instruction postInstruction = postInsertions[oldOffset]; if (postInstruction != null) { postInstruction.accept(classFile, methodInfo, codeAttrInfo, oldOffset, this); postInstruction.write(codeAttrInfo, newOffset); } } /** * Adjusts the given jump offsets for the instruction at the given offset. */ private void remapJumpOffsets(int offset, int[] jumpOffsets, int length) { for (int index = 0; index < length; index++) { jumpOffsets[index] = remapBranchOffset(offset, jumpOffsets[index]); } } /** * Computes the new branch offset for the instruction at the given offset * with the given branch offset. */ private int remapBranchOffset(int offset, int branchOffset) { return remapInstructionOffset(offset + branchOffset) - remapInstructionOffset(offset); } /** * Computes the new instruction offset for the instruction at the given offset. */ private int remapInstructionOffset(int offset) { if (offset < 0 || offset > codeLength) { throw new IllegalArgumentException("Invalid instruction offset ["+offset+"] in code with length ["+codeLength+"]"); } return instructionOffsetMap[offset]; } /** * Returns the given list of exceptions, without the ones that have empty * code blocks. */ private int removeEmptyExceptions(ExceptionInfo[] exceptionInfos, int exceptionInfoCount) { // Overwrite all empty exceptions. int newIndex = 0; for (int index = 0; index < exceptionInfoCount; index++) { ExceptionInfo exceptionInfo = exceptionInfos[index]; if (exceptionInfo.u2startpc < exceptionInfo.u2endpc) { exceptionInfos[newIndex++] = exceptionInfo; } } return newIndex; } /** * Returns the given list of line numbers, without the ones that have empty * code blocks. */ private int removeEmptyLineNumbers(LineNumberInfo[] lineNumberInfos, int lineNumberInfoCount, int codeLength) { // Overwrite all empty localVariables. int newIndex = 0; for (int index = 0; index < lineNumberInfoCount; index++) { LineNumberInfo lineNumberInfo = lineNumberInfos[index]; int startpc = lineNumberInfo.u2startpc; if ( startpc < codeLength && (index == 0 || startpc > lineNumberInfos[index-1].u2startpc)) { lineNumberInfos[newIndex++] = lineNumberInfo; } } return newIndex; } /** * Returns the given list of local variables, without the ones that have empty * code blocks. */ private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos, int localVariableInfoCount) { // Overwrite all empty exceptions. int newIndex = 0; for (int index = 0; index < localVariableInfoCount; index++) { LocalVariableInfo localVariableInfo = localVariableInfos[index]; if (localVariableInfo.u2length > 0) { localVariableInfos[newIndex++] = localVariableInfo; } } return newIndex; } /** * Returns the given list of local variable types, without the ones that * have empty code blocks. */ private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos, int localVariableTypeInfoCount) { // Overwrite all empty exceptions. int newIndex = 0; for (int index = 0; index < localVariableTypeInfoCount; index++) { LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index]; if (localVariableTypeInfo.u2length > 0) { localVariableTypeInfos[newIndex++] = localVariableTypeInfo; } } return newIndex; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -