Debugging in Android Studio... off by a line? - android

Something has been bothering me for awhile, and I'm wondering if I'm misremembering how things work or if something is wrong with my IDE setup.
Say I have a method
public void normalDebuggerBehavior(String x) {
(BP) int y = 12;
int z = 10;
}
If I set a breakpoint on the first line of the method (BP), and the debugger stops on that breakpoint, shouldn't I be able to see the value of the passed parameter x without needing to step to the next line (int z = 10) either by right-clicking -> evaluate expression or by adding it to the watchlist? I would think this would be in scope at this point.
If I'm not able to do this, and I'm supposed to be able, what would cause this?
Screenshot:
Stepping to the next line brings vendor into scope. Yes, this is a "fresh" compile.

Debuggers run on bytecode and not on Java source code. The mapping between Java source and bytecode is not always one-to-one.
When you place a breakpoint on the first line of a method, it is placed on the method entry point in the bytecode. The bytecode that actually reads in the method parameters has not been executed yet. You can observe this by looking at the bytecode disassembly and noticing the aload instructions at the beginning of a method with parameters.

I would assume that, since you are not using the argument x (in your example) the compiler gets rid of it, thus the debugger cant "see" it.
I think its a similar thing in your picture. It might be that the compiler optimises some stuff and thus the debugger cant see some variables...

Try turning off your jacoco test coverage off for the debug build in your build.gradle file:
debug {
...
testCoverageEnabled false
}
This completely fixed the issue for me.

Related

Proguard deletes method parameters

Recently I found very strange thing with ProGuard. I have this code snippet
As you can see, method showTipHoodLock takes 2 parameters, fragmentManager and top (some offset)
but after I compile the app with minifyEnabled true
I got this on click callback
and this is Utils.showTipHoodLock method
As you can see, proguard deleted 2nd parameter (named top) from method signature and replaced its occurances with 0 literal.
Is it a bug, or a feature, or did I miss something?
P.S. If I change values in line
int coords[] = {0, 0}
to any other numbers, then everything works perfect, and nothing is deleted. Moreover The same snippet of code (which is copy-pasted) in different part of application (in other fragment), starts to work.
Is it a bug, or a feature, or did I miss something?
This is NOT a bug, this is a feature to optimise your code.
According to your piece of code, the second parameter is referenced by following logic as READ ONLY and its value is FIXED to be 0.
Proguard will remove (a kind of Proguard optimisation: Remove unused parameters or Propagate constant arguments) this parameter with this KNOWN FIXED value to simplify the invocation flow.

Is there a way to check for unnecessary #SuppressWarnings annotations?

I've recently begun using annotions to help reduce my lint warning count to filter out valid use-cases of warnings/errors.
As an example, let's assume I am 100% correct in having a variable that is never assigned a value (it's being done via GSON serialization but never x = 2 type assignment). Lint reports this as unused variable. I can add the #SuppressWarnings("unused") annotation and lint skips this.
Sometime in the future, would I be able to do an assignment to the x variable, and then have lint notify me that the #SuppressWarnings("unused") flag is no longer necessary? If not, I'd potentially have unneeded code in my application which I would like to avoid.
Any thoughts?

Why is GDB "jumping back" when debugging with c source codes

I'm debugging the goldfish android kernel (version 3.4), with kernel sources.
Now I found that gdb sometimes jump back and forth between lines, e.g consider c source code like the following:
char *XXX;
int a;
...
if (...)
{
}
When I reached the if clause, I type in n and it will jump back to the int a part. Why is that?
If I execute that command again, it would enter the brackets in the if.
If possible, I want to avoid that part, and enter the if directly (of course, if condition matches)
When I reached the if clause, I type in n and it will jump back to the int a part. Why is that?
Because your code is compiled with optimization on, and the compiler can (and often does) re-arrange instructions of your program in such a way that instructions "belonging" to different source lines are interleaved (code motion optimizations attempt (among other things) to move load instructions to long before their results are needed; this helps to hide memory latency).
If you are using gcc-4.8 or later, build your sources with -Og. Else, see this answer.

Ant how to comment out code for release builds

I was hoping for a way to comment out code on release versions.
What led me to Ant was that Proguard's way of removing Log.D (debug) calls was unsatisfactory as it was leaving the string literals in the dex files, even though the Log.D code was being removed by it's optimisation technique.
As pointed out on this thread
Removing unused strings during ProGuard optimisation
There someone one has suggested Ant could be used with a replace algorithm but this wipes out the code when it is run. I was hoping if there was a way of commenting out the code so it became //ant Log.d, then once it compiles the //ant could be removed.
I am new to ant, and I wasn't able to find any search results for commenting out code in Ant. Is it not a recommended practice? I feel copying all the files to another directory and then removing the lines and then copying it back is overkill. If the compile fails you are left with your code in another directory.
So at the moment I am using the below regex pattern to comment out the code.
<regexp pattern="(\s*)Log\.d\s*(\(.*\))\s*;"/>
<substitution expression="\1\/\/AntComment Log\.d\2;"/>
I was wondering if there is a better way i.e. a built in way of handling comments.
Also is there a way trial run ant regex statements to see what it picks up?
Listening to Jean Waghetti i tried a few bits of code with conditional compilation
I just tried a few variations, it seems it needs you to have if(DEBUG) in the same function. So this piece of code will end up having the string literal in the classes.dex file.
Logger.myLog("Sensitive Info" + c); // you call this
//in Logger class - myLog method
static void myLog(String msg){
if(DEBUG){
If you try to have a bit more sophisticated logging, where it needs figure out whether to log but with an and (&&) with DEBUG it ends up adding the string literal in the dex file eg:
public class SomeClass{
public final boolean log = DEBUG && figure_Log();
private boolean figure_Log(){
// some condition based on other settings
}
//in the code
if (log){
To achieve a more sophisticated logging you have to have this:
if(DEBUG && log){
before all logging calls, it creates too many unused code warnings and looks ugly for me.
You can put the code to be removed on a conditional block depending on a final static field.
static final DEBUG = false;
if (DEBUG) {
System.out.println("debug message");
}
The Java Language Specification has some words about "conditional compilation". It does not enforce it, but the code in the if block can be optimized and not compiled in your class. Oracle javac does this.
You can pass your classes through proguard optimization and it will (almost) certainly strip this part of code if your compiler didn't before.

better way to do Debug only assert code

I am writing my first Android application and I am liberally using asserts() from junit.framework.Assert
I would like to find a way to ensure that the asserts are only compiled into the debug build, not in the release build.
I know how to query the android:debuggable attribute from the manifest so I could create a variable and accomplish this in the following fashon:
static final boolean mDebug = ...
if (mDebug)
Assert.assertNotNull(view);
Is there a better way to do this? i.e. I would prefer not to use an if() with each assert.
thanks
I think the Java language's assert keyword is likely what you want. Under the covers, the assert keyword essentially compiles into Dalvik byte code that does two things:
Checks whether the static variable assertionsDisabled (set in the class' static constructor via a call to java.lang.Class.desiredAssertionStatus()) is != 0 and if so, does nothing
If it is 0, then it checks the assertion expression and throws a java.lang.AssertionError if the expression resolves to false, effectively terminating your application.
The Dalvik runtime by default has assertions turned off, and therefore desiredAssertionStatus always returns 1 (or more precisely, some non-zero value). This is akin to running in "retail" mode. In order to turn on "debug" mode, you can run the following command against the emulator or the device:
adb shell setprop debug.assert 1
and this should do the trick (should work on the emulator or any rooted debugging-ready device).
Note however that the aforementioned Dalvik code that checks the value of assertionsDisabled and throws an AssertionError if the expression is false is always included in your byte code and liberal sprinkling of asserts in your code may lead to byte code bloat.
Please see this for a bit more detail: Can I use assert on Android devices?
If you're concerned about shipping code with the JUnit asserts in (or any other class path), you can use the ProGuard config option 'assumenosideeffects', which will strip out a class path on the assumption that removing it does nothing to the code.
Eg.
-assumenosideeffects class junit.framework.Assert {
*;
}
I have a common debug library I put all my testing methods in, and then use this option to strip it from my released apps.
This also removes the hard to spot problem of strings being manipulated that are never used in release code. For example if you write a debug log method, and in that method you check for debug mode before logging the string, you are still constructing the string, allocating memory, calling the method, but then opting to do nothing. Stripping the class out then removes the calls entirely, meaning as long as your string is constructed inside the method call, it goes away as well.
Make sure it is genuinely safe to just strip the lines out however, as it is done with no checking on ProGuard's part. Removing any void returning method will be fine, however if you are taking any return values from whatever you are removing, make sure you aren't using them for actual operational logic.
I mean if you were using a language feature, like assert(), the compiler should be able to strip that out. But this is an actual class and if a class is referenced by executable code it will be included or assumed included in the final product by the compiler.
However there is nothing stopping you from creating a script that removes all the references to the Assert class in all of your code base before compilation.
Another approach would be to make a test project that targets your application and within JUnit tests actually calls the Assert on the areas which you want to make sure work. I personally like this approach because it is a nice and clean separation of test and application.
If you are just worried about the having an if-statement everywhere, then just wrap Assert with your own class, DebuggableAssert which does that check before each call to Assert.X. It will be sort of less performant because of the method entry/exit and the conditionals but if you can maintain your code better then it might be worth it.

Categories

Resources