examples
examples copied to clipboard
Fixed application crash issue due to NullPointerException on exit
There is an issue when application is closed. tlModel
is set to null in onDestroy()
but InferenceThread
still calls tlModel.predict
method without checking a null.
Prediction[] predictions = tlModel.predict(rgbImage);
java.lang.NullPointerException
is thrown at this line. Solved it using try-catch.
@yyoon Thanks for reviewing my PR.
First I would like to answer your second question.
- Also, please add a comment explaining why the NullPointerException can be thrown and why we are ignoring it.
As you can see here, in the OnDestroy()
method, tlModel
is set to a null
.
public void onDestroy() {
super.onDestroy();
tlModel.close();
tlModel = null; // <== tlModel is now a null reference
Log.d("TFL","onDestroy() completed");
}
For some reason(I am searching) imageAnalysis
use-case is not being unbounded on application exit after onDestroy
is completed. As shown below, eventually a call to tfmodel.predict
method is made inside inferenceAnalyzer
even after tfModel
is set to a null
and throws a NullPointerExecption
.
private final ImageAnalysis.Analyzer inferenceAnalyzer =
(imageProxy, rotationDegrees) -> {
...
Log.d("TFL","Incoming req for predict");
Prediction[] predictions = tlModel.predict(rgbImage);
...
}
The exact exception thrown is this,
java.lang.NullPointerException: Attempt to invoke virtual method 'org.tensorflow.lite.examples.transfer.api.TransferLearningModel$Prediction[] org.tensorflow.lite.examples.transfer.TransferLearningModelWrapper.predict(float[])' on a null object reference
at org.tensorflow.lite.examples.transfer.CameraFragment.lambda$new$2$CameraFragment(CameraFragment.java:180)
at org.tensorflow.lite.examples.transfer.-$$Lambda$CameraFragment$o2DkVL-ukwqtN87dNJz2_ON_zV8.analyze(Unknown Source:2)
at androidx.camera.core.ImageAnalysisNonBlockingCallback$1.run(ImageAnalysisNonBlockingCallback.java:150)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.os.HandlerThread.run(HandlerThread.java:65)
I have logged the sequence of method calls as show below. You can see that last request for prediction is after completion of onDestroy()
which is the reason for NullPointerException
.
2020-04-27 19:45:57.904 5247-5284/org.tensorflow.lite.examples.transfer D/TFL: Incoming req for predict
2020-04-27 19:45:58.219 5247-5284/org.tensorflow.lite.examples.transfer D/TFL: Incoming req for predict
2020-04-27 19:45:58.534 5247-5284/org.tensorflow.lite.examples.transfer D/TFL: Incoming req for predict
2020-04-27 19:45:58.855 5247-5284/org.tensorflow.lite.examples.transfer D/TFL: Incoming req for predict
2020-04-27 19:45:59.146 5247-5247/org.tensorflow.lite.examples.transfer D/TFL: onDestroy() completed
2020-04-27 19:45:59.227 5247-5284/org.tensorflow.lite.examples.transfer D/TFL: Incoming req for predict
Now coming to the first question.
Could you specifically catch NullPointerException instead? It would be bad to catch all exceptions and ignore them in case something else happens.
Yes sure. I can handle NullPointerException
specifically and it solves the app crash. But the primary reason for imageAnalysis
use-case not getting unbound is still unknown.
Catching a NullPointerException is probably not what we want, we should either add a proper lock for inference or do the closing on the worker thread rather than the UI thread.