public RecoverResult recover() {
        if (!loadHeader()) {
            return RecoverResult.newInstance(false, false, -1);
        }
        final ByteBuffer byteBuffer = sliceByteBuffer();
        int recoverPosition = this.header.getHeaderSize();
        int recoverCnt = 0;
        int lastLogPosition = recoverPosition;
        boolean isFileEnd = false;
        final long start = Utils.monotonicMs();
        while (true) {
            byteBuffer.position(recoverPosition);
            final CheckDataResult checkResult = checkData(byteBuffer);
            if (checkResult == CheckDataResult.FILE_END) {
                // File end
                isFileEnd = true;
                break;
            } else if (checkResult == CheckDataResult.CHECK_FAIL) {
                // Check fail
                break;
            } else {
                // Check success
                recoverCnt++;
                lastLogPosition = recoverPosition;
                recoverPosition += checkResult.size;
            }
        }
        updateAllPosition(recoverPosition);
        onRecoverDone(lastLogPosition);
        LOG.info("Recover file {} cost {} millis, recoverPosition:{}, recover logs:{}, lastLogIndex:{}", getFilePath(),
            Utils.monotonicMs() - start, recoverPosition, recoverCnt, getLastLogIndex());
        final boolean isRecoverTotal = isFileEnd || (recoverPosition == this.fileSize);
        return RecoverResult.newInstance(true, isRecoverTotal, recoverPosition);
    }
Recover logic
@return the last recover position
jraft-extension/java-log-storage-impl/src/main/java/com/alipay/sofa/jraft/storage/file/AbstractFile.java