I just learned about Log.wtf ("What a Terrible Failure" lol) and I'm wondering when I should use it.
What is the difference between calling Log.wtf with an exception and letting an exception go unhandled (crash)?
How does it affect crash reports in the Google Play Developer Console?
I usually throw an IllegalStateException for unexpected conditions. Should I consider calling Log.wtf instead?
Edit:
See also: Under what circumstances will Android's Log.wtf terminate my app?
What Log.wtf does is write the exception and its stack trace in the log, and only that. It neither catches nor throws exceptions. So
The difference is the exception is logged or not. The exception remains unhandled.
It doesn't affect crash reports.
If you wish to log it, go ahead. But you'll want to keep throwing IllegalStateException.
EDIT
I tried debugging and stepping into Log.wtf but no luck.
What I've found is pretty much what is answered in the linked question. It seems that in the "default terrible failure handling" Log.wtf creates an internal exception (TerribleFailure) which wraps any given exception. Then it calls RuntimeInit.wtf(). Its javadoc says:
Report a serious error in the current process. May or may not cause
the process to terminate (depends on system settings).
I guess the behavior of Log.wtf is up to the device manufacturer. My Sony C6503 doesn't seem to raise any exception or kill the process.
Some open source reference:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/Log.java
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/com/android/internal/os/RuntimeInit.java
Unhandled exceptions are not logged by default. Log.wtf may or may not crash the application. If you pass an exception to Log.wtf and it crashes, then you should get a stack trace similar to what you would get if the exception were not handled. After calling Log.wtf, you should (re)throw an exception if you want to ensure a crash (without catching it of course).
There may be specific use cases for Log.wtf, but if you are unsure, it's probably better to use Log.e instead.
Related
During debugging of Android app, sometimes InterruptedException occurs and crashes the app. I've been able to set a break-point on default exception handler, but call stack is not informative.
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:1991)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2025)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1048)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:776)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1035)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1097)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:820)
What is telling is that the interrupted thread is always RxCachedThreadScheduler-4 (or some other number)
What would be a systematic approach towards finding the root cause of the exception?
Set breakpoint at the method Thread::interrupt and catch the offender. If you think that this interruption should not happen, and you cannot switch off the call which interrupts your thread, then you can override Thread::interrupt in your thread implementation, and force the the thread pool to use your implementation by providing your own ThreadFactory.
It looks like the crash is happening from a third party code package, you should post your issue with the source project as well for additional help. Please post any code related to how you use this package to help troubleshoot too. Make sure you're using the latest version of this package in case they already fixed this issue. The stack trace isn't very helpful because the other project is launching threads and the crash happens from within one of their threads. Likely, you're not using the package as intended or there is a bug in it that they need to fix.
https://github.com/ReactiveX/RxJava
I have a try block and a catch block where NullPointerExceptions are caught. However, Lint warns that a statement in the try block may cause a NullPointerException, even though the exception will be caught. Why doesn't lint recognise that I have handled the possibility of the exception?
I am using Android Studio 3. Thanks.
As written here,
Programs must not catch java.lang.NullPointerException. A NullPointerException exception thrown at runtime indicates the existence of an underlying null pointer dereference that must be fixed in the application code. Handling the underlying null pointer dereference by catching the NullPointerException rather than fixing the underlying problem is inappropriate for several reasons. First, catching NullPointerException adds significantly more performance overhead than simply adding the necessary null checks [Bloch 2008]. Second, when multiple expressions in a try block are capable of throwing a NullPointerException, it is difficult or impossible to determine which expression is responsible for the exception because the NullPointerException catch block handles any NullPointerException thrown from any location in the try block. Third, programs rarely remain in an expected and usable state after a NullPointerException has been thrown. Attempts to continue execution after first catching and logging (or worse, suppressing) the exception rarely succeed.
Likewise, programs must not catch RuntimeException, Exception, or Throwable. Few, if any, methods are capable of handling all possible runtime exceptions. When a method catches RuntimeException, it may receive exceptions unanticipated by the designer, including NullPointerException and ArrayIndexOutOfBoundsException. Many catch clauses simply log or ignore the enclosed exceptional condition and attempt to resume normal execution; this practice often violates ERR00-J. Do not suppress or ignore checked exceptions. Runtime exceptions often indicate bugs in the program that should be fixed by the developer and often cause control flow vulnerabilities.
So, it appears like intentional behavior when Android Studio "ignores" NullPointerException catch blocks, and you should not be catching NullPointerException, instead just check for null.
See also this question.
The linter's job is to warn you of code that could be a problem. One of the built-in rules checks for dereferences that could cause NullPointerExceptions; it doesn't then check to see if this exception is caught.
However, I'm left wondering why you catch (NullPointerException e) instead of simply checking for null values and then proactively handling them.
So, Android built in this "feature", that any exception which has an UnknownHostException in its cause stack will not have its stack trace logged when passed into Log.X methods... See for example the questions here or here. Or check the original commit which introduced this (n.b. the comment).
Personally I consider this to be a really stupid decision: in my case this so called feature even prevents any kind of toString() call on my custom exceptions, so if any error or exception at any point was caused by UnknownHostException it'll log just... nothing. :/ (Well yes, I get the timestamp, tag, etc. but no actual logged content.)
Is there any way around this issue, except for replacing the logging framework with something else entirely?
Is there some config I haven't found or some other clever way to fix logging?
I would like to be able to determine, in case an exception occurs while the user is using my application, where exactly the exception took place. I'd like to do something similar ti printStackTrace() method. (So this is during build mode, not debug mode )
Currently I've put almost all my methods from all my classes inside a try-catch statement (each method has a try-catch statement which encompasses all it's instructions) and i can, at this point, display the "tree" or stack of methods if an exception occurs. But is there a way to determine either a line number of something to more precisely indicate where inside the method the exception occurred? Similar to what is displayed when you use printStackTrace().
I'm not really used with Exception handling, what is the best practice for doing this and can in be done?
EDIT
And one other thing. When i use printStackTrace() during build mode, where does it display the content, because Logcat isn't available? Can i retrieve that information and maybe do something with it?
OR
Even better, can i use getStackTrace() during build mode and convert the stuff there in String and maybe output it somewhere?
All the exceptions that are not handled by your code and make your app crash in release mode will appear in the android developper console, close to your app.
For this to work, you will need to retrace obfuscated stack traces.
About exception handling : I suggest you read this for instance. You are making a mistake about exception handling if you surround all your code by a try/catch block.
Exception handling is more subtile than that and is often influenced by design considerations (whether to treat exceptions locally or throw them back to the caller).
To sum up : in the core of your app : don't treat exception but throw them or let them be thrown, using the throws clause of your methods signatures. In the upper layers, closer to the UI, treat exceptions with try/catch and if an error occurs, make sure your app is in a stable state and display some usefull messages to users.
More details (but not that much) :
in the database layer : throw exception. You can still catch them to log them, but throw or rethrow them to tell caller that something went wrong.
in the business layer : catch them, make sure your business/domain model is in a stable state and recovers from the error, and throw them back to the caller.
in the UI layer : catch the exceptions and display some messages to users.
My app uses Flurry for analytics and the excellent ACRA for uncaught exception reporting. This means that there are 3 places uncaught exception reporting happens: Flurry, ACRA and the crash error report within the Android Developer Console. As far as I can tell, it looks like only one of the 3 areas catches and reports on an exception. And, more strangely, it seems random as to which one it is. I.e. sometimes an exception is reported in ACRA, sometimes in Flurry and sometimes in the Developer Console. I don't have a high enough volume of exceptions (thankfully!) to see any patterns, but ideally I'd like all exceptions at a minimum to go to ACRA. Am I missing something as to how this works? Is it possible for all exceptions to go to all 3 reporting places?
You can disable Flurry's exception handling using this command in your onStart() -
FlurryAgent.setCaptureUncaughtExceptions(false);
This way it won't interfere with other handlers.
Update June 2013
This answer still stands as the way to achieve this goal, but from my experience, Flurry seem to catch an exception here and there in spite of this flag. So it's not a 100% reliable solution. Recently I moved to Google Analytics, and turned off the exception handling - and it is perfectly reliable in that respect.