import java.io.IOException; 
import java.io.PipedInputStream; 
import java.io.PipedOutputStream; 
import java.util.Iterator; 
import java.util.Random; 
import java.util.concurrent.ExecutionException; 
import java.util.concurrent.Future; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.zip.GZIPInputStream; 
import java.util.zip.GZIPOutputStream; 

import static java.lang.String.format; 
import static java.lang.Thread.currentThread; 
import static java.util.concurrent.Executors.newScheduledThreadPool; 
import static java.util.concurrent.TimeUnit.SECONDS; 

public class GZIPInputStreamReadNPE {
	private static final ScheduledExecutorService EXECUTOR = newScheduledThreadPool(8); 

    public static void main(String[] args) { 
        try { 
            test(); 
        } catch (Exception e) { 
            throw new RuntimeException("Test failed its execution", e); 
        } finally { 
            EXECUTOR.shutdownNow(); 
        } 
    } 

    private static void test() throws Exception { 

        PipedOutputStream pos = new PipedOutputStream(); 
        PipedInputStream pis = new PipedInputStream(pos); 

        GZIPOutputStream gos = new GZIPOutputStream(pos, true); 
        GZIPInputStream gis = new GZIPInputStream(pis); 

        EXECUTOR.submit(() -> { 
            Iterator<Integer> values = new Random().ints(0, 256).iterator(); 
            while (!currentThread().isInterrupted()) { 
                gos.write(values.next()); 
                gos.flush(); 
            } 
            return null; 
        }); 

        EXECUTOR.schedule(() -> { 
            gis.close(); 
            return null; 
        }, 1, SECONDS); 

        Future<Void> reader = 
        EXECUTOR.submit(() -> { 
            while (gis.read() != -1); 
            return null; 
        }); 

        try { 
            reader.get(); 
        } catch (ExecutionException e) { 
            e.printStackTrace(); 
            if (e.getCause() instanceof IOException) { 
                System.out.println("The test passed, GZIPInputStream#read threw a java.io.IOException when reading from a closed stream."); 
            } else { 
                System.out.println(format("The test failed, GZIPInputStream#read threw an unexpected %s when reading from a closed stream.", (e.getCause() != null) ? e.getCause().getClass() : null)); 
            } 
        } 
    } 
}
