Code review comment: How about describing the root cause here? something like:  >  sort state handles by offsets to avoid building `SnappyFramedInputStream` with EOF stream.  And IIUC,  we only need to sort the state handles when compression is enabled?

Code under review:
public Void restore() throws Exception {
        if (stateHandles.isEmpty()) {
            return null;
        }

        for (OperatorStateHandle stateHandle : stateHandles) {

            if (stateHandle == null) {
                continue;
            }

            FSDataInputStream in = stateHandle.openInputStream();
            closeStreamOnCancelRegistry.registerCloseable(in);

            ClassLoader restoreClassLoader = Thread.currentThread().getContextClassLoader();

            try {
                Thread.currentThread().setContextClassLoader(userClassloader);
                OperatorBackendSerializationProxy backendSerializationProxy =
                        new OperatorBackendSerializationProxy(userClassloader);

                backendSerializationProxy.read(new DataInputViewStreamWrapper(in));

                List<StateMetaInfoSnapshot> restoredOperatorMetaInfoSnapshots =
                        backendSerializationProxy.getOperatorStateMetaInfoSnapshots();

                
                for (StateMetaInfoSnapshot restoredSnapshot : restoredOperatorMetaInfoSnapshots) {

                    final RegisteredOperatorStateBackendMetaInfo<?> restoredMetaInfo =
                            new RegisteredOperatorStateBackendMetaInfo<>(restoredSnapshot);

                    if (restoredMetaInfo.getPartitionStateSerializer()
                            instanceof UnloadableDummyTypeSerializer) {

                        
                        
                        
                        
                        
                        
                        

                        throw new IOException(
                                "Unable to restore operator state ["
                                        + restoredSnapshot.getName()
                                        + "]."
                                        + " The previous typeSerializer of the operator state must be present; the typeSerializer could"
                                        + " have been removed from the classpath, or its implementation have changed and could"
                                        + " not be loaded. This is a temporary restriction that will be fixed in future versions.");
                    }

                    PartitionableListState<?> listState =
                            registeredOperatorStates.get(restoredSnapshot.getName());

                    if (null == listState) {
                        listState = new PartitionableListState<>(restoredMetaInfo);

                        registeredOperatorStates.put(
                                listState.getStateMetaInfo().getName(), listState);
                    } else {
                        
                        
                    }
                }

                
                List<StateMetaInfoSnapshot> restoredBroadcastMetaInfoSnapshots =
                        backendSerializationProxy.getBroadcastStateMetaInfoSnapshots();

                for (StateMetaInfoSnapshot restoredSnapshot : restoredBroadcastMetaInfoSnapshots) {

                    final RegisteredBroadcastStateBackendMetaInfo<?, ?> restoredMetaInfo =
                            new RegisteredBroadcastStateBackendMetaInfo<>(restoredSnapshot);

                    if (restoredMetaInfo.getKeySerializer() instanceof UnloadableDummyTypeSerializer
                            || restoredMetaInfo.getValueSerializer()
                                    instanceof UnloadableDummyTypeSerializer) {

                        
                        
                        
                        
                        
                        
                        

                        throw new IOException(
                                "Unable to restore broadcast state ["
                                        + restoredSnapshot.getName()
                                        + "]."
                                        + " The previous key and value serializers of the state must be present; the serializers could"
                                        + " have been removed from the classpath, or their implementations have changed and could"
                                        + " not be loaded. This is a temporary restriction that will be fixed in future versions.");
                    }

                    BackendWritableBroadcastState<?, ?> broadcastState =
                            registeredBroadcastStates.get(restoredSnapshot.getName());

                    if (broadcastState == null) {
                        broadcastState = new HeapBroadcastState<>(restoredMetaInfo);

                        registeredBroadcastStates.put(
                                broadcastState.getStateMetaInfo().getName(), broadcastState);
                    } else {
                        
                        
                    }
                }

                
                List<Map.Entry<String, OperatorStateHandle.StateMetaInfo>> entries =
                        stateHandle.getStateNameToPartitionOffsets().entrySet().stream()
                                .sorted(
                                        Comparator.comparingLong(
                                                entry -> {
                                                    OperatorStateHandle.StateMetaInfo
                                                            stateMetaInfo = entry.getValue();
                                                    long[] offsets = stateMetaInfo.getOffsets();
                                                    if (offsets == null || offsets.length == 0) {
                                                        return Long.MIN_VALUE;
                                                    } else {
                                                        return offsets[0];
                                                    }
                                                }))
                                .collect(Collectors.toList());

                
                for (Map.Entry<String, OperatorStateHandle.StateMetaInfo> nameToOffsets : entries) {

                    final String stateName = nameToOffsets.getKey();

                    PartitionableListState<?> listStateForName =
                            registeredOperatorStates.get(stateName);
                    final StreamCompressionDecorator compressionDecorator =
                            backendSerializationProxy.isUsingStateCompression()
                                    ? SnappyStreamCompressionDecorator.INSTANCE
                                    : UncompressedStreamCompressionDecorator.INSTANCE;
                    
                    
                    try (final CompressibleFSDataInputStream compressedIn =
                            new CompressibleFSDataInputStream(
                                    in,
                                    compressionDecorator)) { 
                        
                        if (listStateForName == null) {
                            BackendWritableBroadcastState<?, ?> broadcastStateForName =
                                    registeredBroadcastStates.get(stateName);
                            Preconditions.checkState(
                                    broadcastStateForName != null,
                                    "Found state without "
                                            + "corresponding meta info: "
                                            + stateName);
                            deserializeBroadcastStateValues(
                                    broadcastStateForName, compressedIn, nameToOffsets.getValue());
                        } else {
                            deserializeOperatorStateValues(
                                    listStateForName, compressedIn, nameToOffsets.getValue());
                        }
                    }
                }

            } finally {
                Thread.currentThread().setContextClassLoader(restoreClassLoader);
                if (closeStreamOnCancelRegistry.unregisterCloseable(in)) {
                    IOUtils.closeQuietly(in);
                }
            }
        }
        return null;
    }

Line commented on: List<Map.Entry<String, OperatorStateHandle.StateMetaInfo>> entries =

Revised code:
public Void restore() throws Exception {
        if (stateHandles.isEmpty()) {
            return null;
        }

        for (OperatorStateHandle stateHandle : stateHandles) {

            if (stateHandle == null) {
                continue;
            }

            FSDataInputStream in = stateHandle.openInputStream();
            closeStreamOnCancelRegistry.registerCloseable(in);

            ClassLoader restoreClassLoader = Thread.currentThread().getContextClassLoader();

            try {
                Thread.currentThread().setContextClassLoader(userClassloader);
                OperatorBackendSerializationProxy backendSerializationProxy =
                        new OperatorBackendSerializationProxy(userClassloader);

                backendSerializationProxy.read(new DataInputViewStreamWrapper(in));

                List<StateMetaInfoSnapshot> restoredOperatorMetaInfoSnapshots =
                        backendSerializationProxy.getOperatorStateMetaInfoSnapshots();

                
                for (StateMetaInfoSnapshot restoredSnapshot : restoredOperatorMetaInfoSnapshots) {

                    final RegisteredOperatorStateBackendMetaInfo<?> restoredMetaInfo =
                            new RegisteredOperatorStateBackendMetaInfo<>(restoredSnapshot);

                    if (restoredMetaInfo.getPartitionStateSerializer()
                            instanceof UnloadableDummyTypeSerializer) {

                        
                        
                        
                        
                        
                        
                        

                        throw new IOException(
                                "Unable to restore operator state ["
                                        + restoredSnapshot.getName()
                                        + "]."
                                        + " The previous typeSerializer of the operator state must be present; the typeSerializer could"
                                        + " have been removed from the classpath, or its implementation have changed and could"
                                        + " not be loaded. This is a temporary restriction that will be fixed in future versions.");
                    }

                    PartitionableListState<?> listState =
                            registeredOperatorStates.get(restoredSnapshot.getName());

                    if (null == listState) {
                        listState = new PartitionableListState<>(restoredMetaInfo);

                        registeredOperatorStates.put(
                                listState.getStateMetaInfo().getName(), listState);
                    } else {
                        
                        
                    }
                }

                
                List<StateMetaInfoSnapshot> restoredBroadcastMetaInfoSnapshots =
                        backendSerializationProxy.getBroadcastStateMetaInfoSnapshots();

                for (StateMetaInfoSnapshot restoredSnapshot : restoredBroadcastMetaInfoSnapshots) {

                    final RegisteredBroadcastStateBackendMetaInfo<?, ?> restoredMetaInfo =
                            new RegisteredBroadcastStateBackendMetaInfo<>(restoredSnapshot);

                    if (restoredMetaInfo.getKeySerializer() instanceof UnloadableDummyTypeSerializer
                            || restoredMetaInfo.getValueSerializer()
                                    instanceof UnloadableDummyTypeSerializer) {

                        
                        
                        
                        
                        
                        
                        

                        throw new IOException(
                                "Unable to restore broadcast state ["
                                        + restoredSnapshot.getName()
                                        + "]."
                                        + " The previous key and value serializers of the state must be present; the serializers could"
                                        + " have been removed from the classpath, or their implementations have changed and could"
                                        + " not be loaded. This is a temporary restriction that will be fixed in future versions.");
                    }

                    BackendWritableBroadcastState<?, ?> broadcastState =
                            registeredBroadcastStates.get(restoredSnapshot.getName());

                    if (broadcastState == null) {
                        broadcastState = new HeapBroadcastState<>(restoredMetaInfo);

                        registeredBroadcastStates.put(
                                broadcastState.getStateMetaInfo().getName(), broadcastState);
                    } else {
                        
                        
                    }
                }

                List<Map.Entry<String, OperatorStateHandle.StateMetaInfo>> entries =
                        new ArrayList<>(stateHandle.getStateNameToPartitionOffsets().entrySet());

                if (backendSerializationProxy.isUsingStateCompression()) {
                    
                    
                    entries =
                            entries.stream()
                                    .sorted(
                                            Comparator.comparingLong(
                                                    entry -> {
                                                        OperatorStateHandle.StateMetaInfo
                                                                stateMetaInfo = entry.getValue();
                                                        long[] offsets = stateMetaInfo.getOffsets();
                                                        if (offsets == null
                                                                || offsets.length == 0) {
                                                            return Long.MIN_VALUE;
                                                        } else {
                                                            return offsets[0];
                                                        }
                                                    }))
                                    .collect(Collectors.toList());
                }

                
                for (Map.Entry<String, OperatorStateHandle.StateMetaInfo> nameToOffsets : entries) {

                    final String stateName = nameToOffsets.getKey();

                    PartitionableListState<?> listStateForName =
                            registeredOperatorStates.get(stateName);
                    final StreamCompressionDecorator compressionDecorator =
                            backendSerializationProxy.isUsingStateCompression()
                                    ? SnappyStreamCompressionDecorator.INSTANCE
                                    : UncompressedStreamCompressionDecorator.INSTANCE;
                    
                    
                    try (final CompressibleFSDataInputStream compressedIn =
                            new CompressibleFSDataInputStream(
                                    in,
                                    compressionDecorator)) { 
                        
                        if (listStateForName == null) {
                            BackendWritableBroadcastState<?, ?> broadcastStateForName =
                                    registeredBroadcastStates.get(stateName);
                            Preconditions.checkState(
                                    broadcastStateForName != null,
                                    "Found state without "
                                            + "corresponding meta info: "
                                            + stateName);
                            deserializeBroadcastStateValues(
                                    broadcastStateForName, compressedIn, nameToOffsets.getValue());
                        } else {
                            deserializeOperatorStateValues(
                                    listStateForName, compressedIn, nameToOffsets.getValue());
                        }
                    }
                }

            } finally {
                Thread.currentThread().setContextClassLoader(restoreClassLoader);
                if (closeStreamOnCancelRegistry.unregisterCloseable(in)) {
                    IOUtils.closeQuietly(in);
                }
            }
        }
        return null;
    }