Lacti's Archive

Java ObjectStream의 Input/Ouput Blocking이야기

April 29, 2010

Java의 ObjectInputStream / ObjectOutputStream을 사용하여 데이터 통신을 할 때 Client와 Server 양측에서 ObjectInputStream을 먼저 생성하면 프로그램이 더이상 진행되지 않는 경우가 있는데, 그 이유는 다음과 같다.

ObjectInputStream의 ctor 코드를 보면 아래와 같이 readStreamHeader(); 함수를 호출한다.

    public ObjectInputStream(InputStream in) throws IOException {
        verifySubclass();
        bin = new BlockDataInputStream(in);
        handles = new HandleTable(10);
        vlist = new ValidationList();
        enableOverride = false;
        readStreamHeader();
        bin.setBlockDataMode(true);
    }

readStreamHeader() 함수는 아래와 같다. 이는 bin이라는 멤버 변수를 사용하여 short값 2개를 읽는다.

    protected void readStreamHeader()
        throws IOException, StreamCorruptedException
    {
        short s0 = bin.readShort();
        short s1 = bin.readShort();

그런데 bin이라는 녀석은 BlockDataInputStream이다.

    /** filter stream for handling block data conversion */
    private final BlockDataInputStream bin;

이 때문에 양측에서 먼저 InputStream을 생성하면 둘다 short 값 2개를 서로 기다리다가 프로그램이 진행이 안되는 것.

이것을 해결하기 위해서 ObjectOutputStream을 먼저 생성하는데, 그 이유는 이와 같다.

ObjectOutputStream의 ctor를 보면, writeStreamHeader(); 를 호출한다.

    public ObjectOutputStream(OutputStream out) throws IOException {
        verifySubclass();
        bout = new BlockDataOutputStream(out);
        handles = new HandleTable(10, (float) 3.00);
        subs = new ReplaceTable(10, (float) 3.00);
        enableOverride = false;
        writeStreamHeader();
        bout.setBlockDataMode(true);
        if (extendedDebugInfo) {
            debugInfoStack = new DebugTraceInfoStack();
        } else {
            debugInfoStack = null;
        }
    }

writeStreamHeader(); 함수에서는 short값 2개를 write한다.

    protected void writeStreamHeader() throws IOException {
        bout.writeShort(STREAM_MAGIC);
        bout.writeShort(STREAM_VERSION);
    }

이것이 바로 ObjectInputStream에서 기다리고 있는 MAGIC_NUMBER였던 것이다.

이와 같은 작용으로 인해 ObjectStream은 서로 Object를 주고받을 준비가 되었는지(양쪽다 ObjectStream인지) 확인하고 데이터를 주고 받을 수 있는 것이다.

결론

  • ObjectInputStream을 양쪽에서 먼저 생성하면 blocking,
  • 따라서 ObjectOutputStream을 먼저 생성해줘야 stream에 값을 write 후, InputStream에서 읽을 수 있으므로 제대로 돌아간다.
Loading script...