问题
I have an android app written in java.
The app basically connects to a device which sends the app messages. The app waits for the messages to come in and then reports them, before processing each message.
I have a Connection class and a Listener class.
The Connection class is started via the constructor, which sets up the Listener class to listen for messages coming in from the device.
When a message comes in, the Listener sends the message to a method in the Connection class, reportMessage(). This is where the message is processed.
The Listener class is on a separate thread.
The code is shown below.
public class Connection
{
private String response;
private String newResponse;
private DataInputStream reader;
private DataOutputStream writer;
private Socket socket;
private boolean keepListening;
private Listener listener;
public Connection (String _ipAddress, int portNumber)
{
newResponse = "";
try
{
socket = new Socket(_ipAddress, _port); //Connect to the server and its socket
writer = new DataOutputStream(socket.getOutputStream()); //Connect to the server to receive and send messages
reader = new DataInputStream(socket.getInputStream());
listener = new Listener(reader, this); //Create a new listener for the client
new Thread(listener).start(); //Set the listener off running
}
catch (Exception e)
{
...
}
}
public synchronized void reportMessage(String message)
{
try
{
if("".equals(newResponse))
{
newResponse = new String();
}
newResponse = newResponse + message;
System.out.println("Message Received: " + newResponse);
processMessage(); //Process the message
}
catch (Exception e)
{
response = e.getCause().toString();
}
}
}
public class Listener implements Runnable
{
private DataInputStream reader = null;
private boolean keepListening;
private String serverMessage;
private Connection connection;
public Listener (DataInputStream inFromServer, Connection connection)
{
reader = inFromServer;
//Get the client connection's message transfer
keepListening = true;
this.connection = connection;
}
public void run()
{
while (keepListening)
{
try
{
if (reader.available() > 0)
{
byte[] readInData = new byte[reader.available()]; //Initialise the array
reader.read (readInData); //Read in the data
serverMessage = Utils.byteToString(readInData);
connection.reportMessage(serverMessage); //Report the message
}
}
catch (IOException e)
{
System.out.println("Error reading." + e.getLocalizedMessage().toString());
keepListening = false;
}
keepListening = connection.getKeepListening();
}
}
}
This works well for a time, then sometimes I receive an error which crashes the program.
When running in debug mode, I get a NullPointerException thrown on whatever is the first line of reportMessage() in the Connection class.
The program is suspended on whatever line is the first line, whether it is a System.out.println or a line of actual code.
And the error doesn't get caught by the try and catch. It crashes the program and there is no handling of the error even though it occurs in the try and catch.
This leads me to believe the error is not being thrown by anything in the reportMessage() method. If this is the case, then perhaps the error is being thrown in the Listener class .run().
However, I cannot see where any NullPointerException can be thrown from, as I have tried to make all the checks and when it is thrown, it is thrown when there are messages being sent.
The debugger says "An exception stack trace is not available".
The LogCat says:
08-21 10:35:57.894: E/AndroidRuntime(1118): FATAL EXCEPTION: Thread-12
08-21 10:35:57.894: E/AndroidRuntime(1118): java.lang.NullPointerException
08-21 10:35:57.894: E/AndroidRuntime(1118):atCom.que.wifiaudio.Connection.reportMessage(Connection.java:339)
08-21 10:35:57.894: E/AndroidRuntime(1118): at com.que.wifiaudio.Listener.reportIncomingMessage(Listener.java:93)
08-21 10:35:57.894: E/AndroidRuntime(1118): at com.que.wifiaudio.Listener.run(Listener.java:67)
08-21 10:35:57.894: E/AndroidRuntime(1118): at java.lang.Thread.run(Thread.java:1102)
Can anyone help me?
I need to know what is throwing the NullPointerException and how to stop it!
EDIT: Thanks to a lot of help, it now turns out it is the Exception I am catching and trying to get the cause of which is null. Still trying to work out where it is coming from though!
回答1:
My guess would be that an exception is thrown in processMessage, caught in the catch bellow it, but the getCause is null.
1/ Try to log the exception before handling it
2/ Look in processMessage, there should be an exception thrown.
回答2:
if((newResponse==null) || ("".equals(newResponse))
Or use brilliant guava's:
if(Strings.isNullOrEmpty(newResponse))
回答3:
message
or newResponse
may be null because it will get converted to message.toString()
and newResponse.toString()
by compiler.
Add condition for null check :
if(message != null && newResponse!=null) {
newResponse = newResponse + message;
} else {
// throw exception ...
}
回答4:
One thing which I see is that in reportMessage(), you are checking whether newResponse is an empty string - however you have not initialized it before, so it is most likely null. Probably what you want is
if(newResponse == null) {
newResponse = new String();
}
回答5:
Instead of:
if("".equals(newResponse))
Use this:
if(newResponse==null)
An empty string is not the same as a null
object; therefore, in cases when newResonse
is null
, it won't be initialized with a proper String
object, and you wind up with the NPE.
来源:https://stackoverflow.com/questions/12070118/nullpointerexception-thrown-in-java-synchronised-method-using-sockets