Skip to content

java.lang.NullPointerException: Attempt to invoke virtual method 'void java.net.Socket.close()' on a null object reference #957

@wengbiancheng

Description

@wengbiancheng

Describe the bug
java.lang.NullPointerException: Attempt to invoke virtual method 'void java.net.Socket.close()' on a null object reference
I have encountered this error many times, but I cannot reproduce it because I found that the error seems to be caused by multi-threaded concurrency.
I found that socket.close () appears in two different threads.
One is the reconnect() and it will call the reset():

private void reset() {

	Thread current = Thread.currentThread();
	if (current == writeThread || current == connectReadThread) {
		throw new IllegalStateException("You cannot initialize a reconnect out of the websocket thread. Use reconnect in another thread to insure a successful cleanup.");
	}
	try {
		closeBlocking();
		if( writeThread != null ) {
			this.writeThread.interrupt();
			this.writeThread = null;
		}
		if( connectReadThread != null ) {
			this.connectReadThread.interrupt();
			this.connectReadThread = null;
		}
		this.draft.reset();
		if( this.socket != null ) {
			this.socket.close();
			this.socket = null;
		}
	} catch ( Exception e ) {
		onError( e );
		engine.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
		return;
	}
	connectLatch = new CountDownLatch( 1 );
	closeLatch = new CountDownLatch( 1 );
	this.engine = new WebSocketImpl( this, this.draft );
}

One is in the WebsocketWriteThread:

private class WebsocketWriteThread implements Runnable {


	@Override
	public void run() {
		Thread.currentThread().setName( "WebSocketWriteThread-" + Thread.currentThread().getId() );
		try {
			runWriteData();
		} catch ( IOException e ) {
			handleIOException( e );
		} finally {
			closeSocket();
			writeThread = null;
		}
	}

	/**
	 * Closing the socket
	 */
	private void closeSocket() {
		try {
			if( socket != null ) {
				socket.close();
			}
		} catch ( IOException ex ) {
			onWebsocketError( webSocketClient, ex );
		}
	}
}

Obviously the reconnect thread and the write thread are not the same thread.This reminds me of a piece of code I saw elsewhere.

public class GcsTest {

private static String mStr = null;

private static void printStrLength() {
    if (null != mStr) {
        int len = mStr.length();
        System.out.println("length = " + len);
    }
}

public static void main(String[] args) {
    GThreadA threadA = new GThreadA();
    GThreadB threadB = new GThreadB();
    threadA.start();
    threadB.start();
}

static class GThreadA extends Thread {
    @Override
    public void run() {
        while (true) {
            if (null == mStr) {
                mStr = "Gcs";
            } else {
                mStr = null;
            }
        }
    }
}

static class GThreadB extends Thread {
    @Override
    public void run() {
        while (true) {
            printStrLength();
        }
    }
}}

It will have a null pointer error.It may take some time to run before the error occurs.After threadB just judged if (null! = mStr), it switched to threadA. At this time, threadA also judged that mStr was not null, so it set mStr to null, and then switched to threadB. When threadB gets the length A null pointer exception occurred.

So when reconnect () happens, is it possible that there are some conditions that triggered closeSocket in writeThread.And when reconnectThread sets the socket to null, just writeThread switches to socket.close().So it happened a null pointer exception and WebsocketWriteThread does not catch null pointer exception,it only catches IOException,so the entire application crashed.

Environment(please complete the following information):

  • Version used:1.4.0
  • Java version:1.8.0_131
  • Operating System and version: Android 9

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions