private void visitJumpInsn(final int opcode, final Label label) {
        lastBytecodeOffset = code.length;
        // Add the instruction to the bytecode of the method.
        // Compute the 'base' opcode, i.e. GOTO or JSR if opcode is GOTO_W or JSR_W, otherwise opcode.
        int baseOpcode =
                opcode >= Constants.GOTO_W ? opcode - Constants.WIDE_JUMP_OPCODE_DELTA : opcode;
        boolean nextInsnIsJumpTarget = false;
        if ((label.flags & Label.FLAG_RESOLVED) != 0
                && label.bytecodeOffset - code.length < Short.MIN_VALUE) {
            // Case of a backward jump with an offset < -32768. In this case we automatically replace GOTO
            // with GOTO_W, JSR with JSR_W and IFxxx <l> with IFNOTxxx <L> GOTO_W <l> L:..., where
            // IFNOTxxx is the "opposite" opcode of IFxxx (e.g. IFNE for IFEQ) and where <L> designates
            // the instruction just after the GOTO_W.
            if (baseOpcode == Opcodes.GOTO) {
                code.putByte(Constants.GOTO_W);
            } else if (baseOpcode == Opcodes.JSR) {
                code.putByte(Constants.JSR_W);
            } else {
                // Put the "opposite" opcode of baseOpcode. This can be done by flipping the least
                // significant bit for IFNULL and IFNONNULL, and similarly for IFEQ ... IF_ACMPEQ (with a
                // pre and post offset by 1). The jump offset is 8 bytes (3 for IFNOTxxx, 5 for GOTO_W).
                code.putByte(baseOpcode >= Opcodes.IFNULL ? baseOpcode ^ 1 : ((baseOpcode + 1) ^ 1) - 1);
                code.putShort(8);
                // Here we could put a GOTO_W in theory, but if ASM specific instructions are used in this
                // method or another one, and if the class has frames, we will need to insert a frame after
                // this GOTO_W during the additional ClassReader -> ClassWriter round trip to remove the ASM
                // specific instructions. To not miss this additional frame, we need to use an ASM_GOTO_W
                // here, which has the unfortunate effect of forcing this additional round trip (which in
                // some case would not have been really necessary, but we can't know this at this point).
                code.putByte(Constants.ASM_GOTO_W);
                hasAsmInstructions = true;
                // The instruction after the GOTO_W becomes the target of the IFNOT instruction.
                nextInsnIsJumpTarget = true;
            }
            label.put(code, code.length - 1, true);
        } else if (baseOpcode != opcode) {
            // Case of a GOTO_W or JSR_W specified by the user (normally ClassReader when used to remove
            // ASM specific instructions). In this case we keep the original instruction.
            code.putByte(opcode);
            label.put(code, code.length - 1, true);
        } else {
            // Case of a jump with an offset >= -32768, or of a jump with an unknown offset. In these
            // cases we store the offset in 2 bytes (which will be increased via a ClassReader ->
            // ClassWriter round trip if it turns out that 2 bytes are not sufficient).
            code.putByte(baseOpcode);
            label.put(code, code.length - 1, false);
        }

        // If needed, update the maximum stack size and number of locals, and stack map frames.
        if (currentBasicBlock != null) {
            Label nextBasicBlock = null;
            currentBasicBlock.frame.execute(baseOpcode, 0, null, null);
            // Record the fact that 'label' is the target of a jump instruction.
            label.getCanonicalInstance().flags |= Label.FLAG_JUMP_TARGET;
            // Add 'label' as a successor of the current basic block.
            addSuccessorToCurrentBasicBlock(label);
            if (baseOpcode != Opcodes.GOTO) {
                // The next instruction starts a new basic block (except for GOTO: by default the code
                // following a goto is unreachable - unless there is an explicit label for it - and we
                // should not compute stack frame types for its instructions).
                nextBasicBlock = new Label();
            }

            // If the next instruction starts a new basic block, call visitLabel to add the label of this
            // instruction as a successor of the current block, and to start a new basic block.
            if (nextBasicBlock != null) {
                if (nextInsnIsJumpTarget) {
                    nextBasicBlock.flags |= Label.FLAG_JUMP_TARGET;
                }
                visitLabel(nextBasicBlock);
            }
            if (baseOpcode == Opcodes.GOTO) {
                endCurrentBasicBlockWithNoSuccessor();
            }
        }
    }
Constructs a new {@link MethodWriter}.

@param symbolTable where the constants used in this AnnotationWriter must be stored.
@param access      the method's access flags (see {@link Opcodes}).
@param name        the method's name.
@param descriptor  the method's descriptor (see {@link Type}).
core/src/main/java/com/alibaba/fastjson2/internal/asm/MethodWriter.java