⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codeinsertion.java

📁 Java Bytecode Editor 是一个 JAVA 的字节码反汇编和修改器。它可以很方便的修改已经编译成 Class 文件的 JAVA 文件。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                                      int[] transformedIndices)
        throws InvalidByteCodeException
    {
        int instructionCount = instructions.size();
        for (int sourceIndex = 0; sourceIndex < instructionCount; sourceIndex++) {
            AbstractInstruction currentInstruction = (AbstractInstruction)instructions.get(sourceIndex);
            int branchOffset = getBranchOffset(currentInstruction);
            if (branchOffset == 0) {
                continue;
            }
            if (currentInstruction instanceof TableSwitchInstruction) {
                int[] jumpOffsets = ((TableSwitchInstruction)currentInstruction).getJumpOffsets();
                for (int i = 0; i < jumpOffsets.length; i++) {
                    int targetIndex = getBranchTargetIndex(instructions, sourceIndex, jumpOffsets[i]);
                    jumpOffsets[i] =
                        calculateNewBranchOffset(newInstructions, sourceIndex, targetIndex, transformedIndices, newOffsets);
                }
            } else if (currentInstruction instanceof LookupSwitchInstruction) {
                List matchOffsetPairs = ((LookupSwitchInstruction)currentInstruction).getMatchOffsetPairs();
                for (int i = 0; i < matchOffsetPairs.size(); i++) {
                    MatchOffsetPair matchOffsetPair =
                        (MatchOffsetPair)matchOffsetPairs.get(i);
                    int targetIndex = getBranchTargetIndex(instructions, sourceIndex, matchOffsetPair.getOffset());
                    matchOffsetPair.setOffset(
                        calculateNewBranchOffset(newInstructions, sourceIndex, targetIndex, transformedIndices, newOffsets)
                    );
                }
            }
            int targetIndex = getBranchTargetIndex(instructions, sourceIndex, branchOffset);

            setBranchOffset(
                currentInstruction,
                calculateNewBranchOffset(newInstructions, sourceIndex, targetIndex, transformedIndices, newOffsets)
            );

        }
    }

    private static int calculateNewBranchOffset(List newInstructions,
                                                int sourceIndex,
                                                int targetIndex,
                                                int[] transformedIndices,
                                                int[] newOffsets)
{
            int transformedSourceIndex = transformedIndices[sourceIndex];
            int transformedTargetIndex = transformedIndices[targetIndex];

            int newBranchOffset = newOffsets[transformedTargetIndex] - newOffsets[transformedSourceIndex];

            return newBranchOffset;
    }


    private static int getBranchOffset(AbstractInstruction instruction) {

        int branchOffset = 0;
        if (instruction.getOpcode() == Opcodes.OPCODE_GOTO_W) {
            branchOffset = ((ImmediateIntInstruction)instruction).getImmediateInt();
        } else if (instruction instanceof TableSwitchInstruction) {
            branchOffset = ((TableSwitchInstruction)instruction).getDefaultOffset();
        } else if (instruction instanceof LookupSwitchInstruction) {
            branchOffset = ((LookupSwitchInstruction)instruction).getDefaultOffset();
        } else if (instruction instanceof BranchInstruction) {
            branchOffset = ((BranchInstruction)instruction).getBranchOffset();
        }
        return branchOffset;
    }

    private static void setBranchOffset(AbstractInstruction instruction,
                                        int branchOffset)
    {
        if (instruction.getOpcode() == Opcodes.OPCODE_GOTO_W) {
            ((ImmediateIntInstruction)instruction).setImmediateInt(branchOffset);
        } else if (instruction instanceof TableSwitchInstruction) {
            ((TableSwitchInstruction)instruction).setDefaultOffset(branchOffset);
        } else if (instruction instanceof LookupSwitchInstruction) {
            ((LookupSwitchInstruction)instruction).setDefaultOffset(branchOffset);
        } else if (instruction instanceof BranchInstruction) {
            ((BranchInstruction)instruction).setBranchOffset(branchOffset);
        }
    }

    private static int getBranchTargetIndex(List instructions,
                                            int sourceIndex,
                                            int branchOffset)
        throws InvalidByteCodeException
    {
        int instructionsCount = instructions.size();
        int startOffset = ((AbstractInstruction)instructions.get(sourceIndex)).getOffset();
        int step = branchOffset > 0 ? 1 : -1;
        for (int i = sourceIndex + step; i >= 0 && i < instructionsCount; i += step) {
            int targetOffset = ((AbstractInstruction)instructions.get(i)).getOffset();
            if (targetOffset - startOffset == branchOffset) {
                return i;
            }
        }
        throw new InvalidByteCodeException("Invalid branch target");
    }

    private static void adjustExceptionTable(int[] oldOffsets,
                                             int[] newOffsets,
                                             int[] transformedIndices,
                                             CodeAttribute codeAttribute)
        throws InvalidByteCodeException
    {

        ExceptionTableEntry[] exceptionTable = codeAttribute.getExceptionTable();
        if (exceptionTable == null) {
            return;
        }

        for (int i = 0; i < exceptionTable.length; i++) {
            ExceptionTableEntry currentEntry = exceptionTable[i];
            int startPcIndex = Arrays.binarySearch(oldOffsets, currentEntry.getStartPc());
            int endPcIndex = Arrays.binarySearch(oldOffsets, currentEntry.getEndPc());
            int handlerPcIndex = Arrays.binarySearch(oldOffsets, currentEntry.getHandlerPc());
            if (startPcIndex < 0 || endPcIndex < 0 || handlerPcIndex < 0 ||
                startPcIndex == oldOffsets.length ||
                endPcIndex == oldOffsets.length ||
                handlerPcIndex == oldOffsets.length)
            {
                throw new InvalidByteCodeException("Invalid exception table");
            }
            currentEntry.setStartPc(newOffsets[transformedIndices[startPcIndex]]);
            currentEntry.setEndPc(newOffsets[transformedIndices[endPcIndex]]);
            currentEntry.setHandlerPc(newOffsets[transformedIndices[handlerPcIndex]]);
        }

   }

    private static void adjustLineNumberTable(int[] oldOffsets,
                                              int[] newOffsets,
                                              int[] transformedIndices,
                                              CodeAttribute codeAttribute)
        throws InvalidByteCodeException
    {

        LineNumberTableAttribute lineNumberTableAttribute =
            (LineNumberTableAttribute)codeAttribute.findAttribute(LineNumberTableAttribute.class);
        if (lineNumberTableAttribute == null) {
            return;
        }
        LineNumberTableEntry[] lineNumberTable = lineNumberTableAttribute.getLineNumberTable();

        for (int i = 0; i < lineNumberTable.length; i++) {
            LineNumberTableEntry currentEntry = lineNumberTable[i];
            int startPcIndex = Arrays.binarySearch(oldOffsets, currentEntry.getStartPc());
            if (startPcIndex < 0 || startPcIndex == oldOffsets.length) {
                throw new InvalidByteCodeException("Invalid line number table " + currentEntry.getStartPc());
            }
            currentEntry.setStartPc(newOffsets[transformedIndices[startPcIndex]]);
        }

   }

    private int position;
    private AbstractInstruction[] preInstructions;
    private AbstractInstruction[] postInstructions;
    private boolean shiftTarget;

    /**
        Create a code insertion.
        @param position the instruction number to which this <tt>CodeInsertion</tt>
                        is to be applied. Corresponds to the index in the list
                        of instructions such as the one returned by a 
                        <tt>ByteCodeReader</tt>.
        @param preInstructions the instructions to be inserted <b>before</b>
                               the insertion point.
        @param postInstructions the instructions to be inserted <b>after</b>
                                the insertion point.
        @param shiftTarget should offsets of branch instructions pointing to 
                           the position of this code insertion
                           be shifted or point to the beginning of the 
                           code inserted via the <tt>preInstructions</tt>
                           parameters.
     */
    public CodeInsertion(int position,
                         AbstractInstruction[] preInstructions,
                         AbstractInstruction[] postInstructions,
                         boolean shiftTarget)
    {
        this.position = position;
        this.preInstructions = preInstructions;
        this.postInstructions  = postInstructions;
        this.shiftTarget = shiftTarget;
    }

    /**
        Get the insertion position, i.e the instruction number to which
        this <tt>CodeInsertion</tt> is to be applied. Corresponds to the
        index in the list of instructions such as the one returned by a 
        <tt>ByteCodeReader</tt>.
        @return the insertion position
     */
    public int getPosition() {
        return position;
    }

    /**
        Set the insertion position, i.e the instruction number to which
        this <tt>CodeInsertion</tt> is to be applied. Corresponds to the
        index in the list of instructions such as the one returned by a 
        <tt>ByteCodeReader</tt>.
        @param position the insertion position
     */
    public void setPosition(int position) {
        this.position = position;
    }

    /**
        Get the instructions to be inserted <b>before</b> the insertion point.
        @return array of instructions
     */
    public AbstractInstruction[] getPreInstructions() {
        return preInstructions;
    }

    /**
        Set the instructions to be inserted <b>before</b> the insertion point.
        @param preInstructions array of instructions
     */
    public void setPreInstructions(AbstractInstruction[] preInstructions) {
        this.preInstructions = preInstructions;
    }

    /**
        Get the instructions to be inserted <b>after</b> the insertion point.
        @return array of instructions
     */
    public AbstractInstruction[] getPostInstructions() {
        return postInstructions;
    }

    /**
        Set the instructions to be inserted <b>after</b> the insertion point.
        @param postInstructions array of instructions
     */
    public void setPostInstructions(AbstractInstruction[] postInstructions) {
        this.postInstructions = postInstructions;
    }

    /**
        Get whether offsets of branch instructions pointing to the position of
        the resulting code insertion should be shifted to the first pre-instruction
        or continue to point at the original instruction.
        @return the boolean value
     */
    public boolean isShiftTarget() {
        return shiftTarget;
    }

    /**
        Set whether offsets of branch instructions pointing to the position of
        the resulting code insertion should be shifted to the first pre-instruction
        or continue to point at the original instruction.
        @param shiftTarget the boolean value.
     */
    public void setShiftTarget(boolean shiftTarget) {
        this.shiftTarget = shiftTarget;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -