📄 codeattributecomposer.java
字号:
localVariableTableAttribute.u2localVariableTableLength = removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable, localVariableTableAttribute.u2localVariableTableLength, codeAttribute.u2maxLocals); } public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) { // Remap all local variable table entries. localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this); // Remove local variables with empty code blocks. localVariableTypeTableAttribute.u2localVariableTypeTableLength = removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable, localVariableTypeTableAttribute.u2localVariableTypeTableLength, codeAttribute.u2maxLocals); } // Implementations for InstructionVisitor. public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { // Adjust the branch offset. branchInstruction.branchOffset = remapBranchOffset(offset, branchInstruction.branchOffset); } public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) { // Adjust the default jump offset. tableSwitchInstruction.defaultOffset = remapBranchOffset(offset, tableSwitchInstruction.defaultOffset); // Adjust the jump offsets. remapJumpOffsets(offset, tableSwitchInstruction.jumpOffsets, tableSwitchInstruction.highCase - tableSwitchInstruction.lowCase + 1); } public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) { // Adjust the default jump offset. lookUpSwitchInstruction.defaultOffset = remapBranchOffset(offset, lookUpSwitchInstruction.defaultOffset); // Adjust the jump offsets. remapJumpOffsets(offset, lookUpSwitchInstruction.jumpOffsets, lookUpSwitchInstruction.jumpOffsetCount); } // Implementations for ExceptionInfoVisitor. public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, 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 StackMapFrameVisitor. public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) { // Remap the stack map frame offset. int stackMapFrameOffset = remapInstructionOffset(offset); int offsetDelta = stackMapFrameOffset; // Compute the offset delta if the frame is part of a stack map frame // table (for JDK 6.0) instead of a stack map (for Java Micro Edition). if (expectedStackMapFrameOffset >= 0) { offsetDelta -= expectedStackMapFrameOffset; expectedStackMapFrameOffset = stackMapFrameOffset + 1; } stackMapFrame.u2offsetDelta = offsetDelta; } public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) { // Remap the stack map frame offset. visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame); // Remap the verification type offset. sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this); } public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) { // Remap the stack map frame offset. visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame); // Remap the verification type offsets. moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this); } public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) { // Remap the stack map frame offset. visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame); // Remap the verification type offsets. fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this); fullFrame.stackAccept(clazz, method, codeAttribute, offset, this); } // Implementations for VerificationTypeVisitor. public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {} public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) { // Remap the offset of the 'new' instruction. uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset); } // Implementations for LineNumberInfoVisitor. public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) { // Remap the code offset. lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC); } // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { // Remap the code offset and length. // TODO: The local variable frame might not be strictly preserved. int startPC = remapInstructionOffset(localVariableInfo.u2startPC); int endPC = remapInstructionOffset(localVariableInfo.u2startPC + localVariableInfo.u2length); localVariableInfo.u2startPC = startPC; localVariableInfo.u2length = endPC - startPC; } // Implementations for LocalVariableTypeInfoVisitor. public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { // Remap the code offset and length. // TODO: The local variable frame might not be strictly preserved. int startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC); int endPC = remapInstructionOffset(localVariableTypeInfo.u2startPC + localVariableTypeInfo.u2length); localVariableTypeInfo.u2length = startPC; localVariableTypeInfo.u2startPC = endPC - startPC; } // Small utility methods. /** * 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 new offset * with the given old branch offset. */ private int remapBranchOffset(int newInstructionOffset, int branchOffset) { if (newInstructionOffset < 0 || newInstructionOffset > codeLength) { throw new IllegalArgumentException("Invalid instruction offset ["+newInstructionOffset +"] in code with length ["+codeLength+"]"); } int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset]; return remapInstructionOffset(oldInstructionOffset + branchOffset) - remapInstructionOffset(oldInstructionOffset); } /** * Computes the new instruction offset for the instruction at the given old * offset. */ private int remapInstructionOffset(int oldInstructionOffset) { if (oldInstructionOffset < 0 || oldInstructionOffset > codeFragmentLengths[level]) { throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset +"] in code fragment with length ["+codeFragmentLengths[level]+"]"); } return instructionOffsetMap[level][oldInstructionOffset]; } /** * 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; } } // Clear the unused array entries. for (int index = newIndex; index < exceptionInfoCount; index++) { exceptionInfos[index] = null; } return newIndex; } /** * Returns the given list of line numbers, without the ones that have empty * code blocks or that exceed the code size. */ private int removeEmptyLineNumbers(LineNumberInfo[] lineNumberInfos, int lineNumberInfoCount, int codeLength) { // Overwrite all empty line number entries. 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; } } // Clear the unused array entries. for (int index = newIndex; index < lineNumberInfoCount; index++) { lineNumberInfos[index] = null; } return newIndex; } /** * Returns the given list of local variables, without the ones that have empty * code blocks or that exceed the actual number of local variables. */ private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos, int localVariableInfoCount, int maxLocals) { // Overwrite all empty local variable entries. int newIndex = 0; for (int index = 0; index < localVariableInfoCount; index++) { LocalVariableInfo localVariableInfo = localVariableInfos[index]; if (localVariableInfo.u2length > 0 && localVariableInfo.u2index < maxLocals) { localVariableInfos[newIndex++] = localVariableInfo; } } // Clear the unused array entries. for (int index = newIndex; index < localVariableInfoCount; index++) { localVariableInfos[index] = null; } return newIndex; } /** * Returns the given list of local variable types, without the ones that * have empty code blocks or that exceed the actual number of local variables. */ private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos, int localVariableTypeInfoCount, int maxLocals) { // Overwrite all empty local variable type entries. int newIndex = 0; for (int index = 0; index < localVariableTypeInfoCount; index++) { LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index]; if (localVariableTypeInfo.u2length > 0 && localVariableTypeInfo.u2index < maxLocals) { localVariableTypeInfos[newIndex++] = localVariableTypeInfo; } } // Clear the unused array entries. for (int index = newIndex; index < localVariableTypeInfoCount; index++) { localVariableTypeInfos[index] = null; } return newIndex; } public static void main(String[] args) { CodeAttributeComposer composer = new CodeAttributeComposer(); composer.beginCodeFragment(10); composer.appendInstruction(0, new SimpleInstruction(InstructionConstants.OP_ICONST_0)); composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ISTORE, 0)); composer.appendInstruction(2, new BranchInstruction(InstructionConstants.OP_GOTO, 1)); composer.beginCodeFragment(10); composer.appendInstruction(0, new VariableInstruction(InstructionConstants.OP_IINC, 0, 1)); composer.appendInstruction(1, new VariableInstruction(InstructionConstants.OP_ILOAD, 0)); composer.appendInstruction(2, new SimpleInstruction(InstructionConstants.OP_ICONST_5)); composer.appendInstruction(3, new BranchInstruction(InstructionConstants.OP_IFICMPLT, -3)); composer.endCodeFragment(); composer.appendInstruction(3, new SimpleInstruction(InstructionConstants.OP_RETURN)); composer.endCodeFragment(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -