I'm not sure if it's my code, but I just noticed in the heap dump I record with Android Studio profiler that when I start setting my variables to null to free up the reference to an object. The object itself is still allocated, and when I check the Android profiler I see that it is due to my ScanCallback. This means every time I do the following logic:
var sensorScanner = SensorScanner(bleAdapter)
sensorScanner = null
my number of allocations keep increasing by 1, but it should not be doing that. If I call that line 24 times, I see 24 allocations.
If I were to comment out the following code in my SensorScanner():
bleAdapter.bluetoothLeScanner.startScan(scanFilters, scanSettings, scanCallback)
the number of allocations will stay at 1 which is what I expect. So if I did 24 allocations experiment again, the allocation stays at 1 when I view the heap dump.
It's weird because I also don't see any exposed methods from the bleAdapter that would allow me to clear the callback.
Thank you for viewing my question, if anyone has some thoughts or tips please share them if possible.
This is the method you must use to stop the scan:
https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner#stopScan(android.bluetooth.le.ScanCallback)
Pass the same callback object you used when you started the scan.
Related
My app uses a proprietary implementation of Canny edge detection based on RenderScript. I tested this on numerous devices with various APIs and it worked very reliably. Now I got the new Samsung S7 working on API23. Here (and only here) I encountered a rather ugly problem. Some of the edge pictures are studded with thousands of artifacts that stem from the Magnitude gradient calculation kernel and are NOT based on actual image information. After trying with all kind of TargetAPIs, taking renderscript.support.mode on and off, etc. I finally found that the problem only arises, when the RenderScript (and Script) instances are used for the second or more times. It does not arise when using them for the first time.
For efficiency reasons I created the RenderScript and Script instances only once in the onCreate method of MainActivity and used it repeatedly thereafter. Of course I don't like to change that.
Does anyone have a solution of this problem? Thanks.
UPDATE: Crazy things are going on here. It seems that freshly created Allocations are NOT empty from the outset! When running:
Type.Builder typeUCHAR1 = new Type.Builder(rs, Element.U8(rs));
typeUCHAR1.setX(width).setY(height);
Allocation alloc = Allocation.createTyped(rs, typeUCHAR1.create());
byte se[] = new byte[width*height];
alloc.copyTo(se);
for (int i=0;i<width*height;i++){
if (se[i]!=0){
Log.e("content: ", String.valueOf(se[i]));
}
}
... the byte Array se is full of funny numbers.... HELP! Any idea, what is going on here?
UPDATE2: I stumbled over my own ignorance here - and really don't deserve a point for this masterpiece.... However, to my defense I must say that the problem was slightly more subtle that it appears here. The context was, that I needed to assign a global allocation (Byte/U8) which initially should be empty (i.e. zero) and then, within the kernel getting partially set to 1 (only where the edges are) via rsSetElementAt_uchar(). Since this worked for many months, I was not aware anymore of the fact, that I didn't explicitely assign the zeros in this allocation.... This only had consequences in API 23, so maybe this can help others not to fall into this trap.... So, note: other than numerical Arrays that are filled with 0 (as by Java default), Allocations cannot assumed to be full of zeros at initiation. Thanks, Sakridge.
Allocation data for primitive types (non-struct/object) is not initialized by default when an Allocation is created unless passed a bitmap using the createFromBitmap api. If you are expecting this then possibly you have a bug in your app which is not exposed when the driver initializes to 0s. It would help if you can post example code which reproduces the problem.
Initialize your allocations by copying from a bitmap or Java array.
I Think i Need Some Help to Understand Garbage Collections, well i know garbage collection clears those who have no referrence from a live Thread, so for example i have a class that Decodes images like this:
new ImageDecoder(MyImageView).Decode();
do i need to keep a reference to the ImageDecoder class and null it later, or it will recycle whenever i call MyImageView.setBackgroundResource(0); ?
or whenever that i create a reference to a class and that Class adds tons of stacks, so whenever i do
MyClass aClass;
...
aClass = null;
Then the Heap Should be Freed From all Heap that Class Took according to the Articles, But It doesnt Happen in real life as i see , how is that working?
thanks alot;
You cant controll in Java and same applies here. Assigning aClass = null doesnt mean GC will run immediately and free memory on heap. It will run when he thinks JVM is running out of memory and creation of new objects require more space then it may run which in case my stop your main thread and freeze your app.
Oracle Java GC Basics
I experience some memory leaks in my android application. I've already used MAT to analyze the memory usage. But I have one question from the DDMS perspectiv in Eclipse, what does 1-byte array[byte[], boolean[]) mean?
Is this specific for my application? You can see that this is the big memory leak issue, this always increases in size, and the rest will increase and decrease randomly. My guess is that the GC doesn't catch this type. Can anybody explain why this happen, with this little information?
One byte array is the designation for any data structure that is organized as a single byte array. In you case and with that size, I would bet in a Bitmap or a Drawble.
Most common reasons for memory leaks are static object not properly managed and holding references to:
Context
View (which holds reference to context (and possibly also to bitmap)
Thread (which are not easly collected by GC)
Handler (which holds reference to context)
Most of them can be solved ensuring that you set the object to null when it's no long required.
Regards.
A byte and a boolean are each 1 byte. If you have an array of those you have a "1-byte array".
A ByteBuffer for example should internally hold one of those.
You have a total of 614 of them where the smallest one be a byte[24] (or boolean[24]), the largest one is 3MB. All of them together use 104MB.
The GC will get rid of them if they are no longer referenced.
For example when you put
private static byte myArray[] = new byte[3 * 1024 * 1024];
in one of your classes and never set it back to null (myArray = null) then this one can't be garbage collected because another Object has a reference to it. The object would be the class itself (as in String.class). The class object can't be garbage collected since classes are never unloaded. (they are referenced by their ClassLoader which could itself be referenced / loaded by another ClassLoader and you can't create Objects & use classes without them - they need to stay and they need to keep a reference to their classes)
It's usually not that simple but often start with static somewhere.
Within MAT (after you force GC) look at the reference chain for the objects that are no longer intended to stay alive and identify the one Object that holds the reference. Set that one to null in your code and your leak is gone. Explained in more detail here:
http://android-developers.blogspot.de/2011/03/memory-analysis-for-android.html
I ran to this problem tonight and almost I checked every bit of code but I couldn't find anything.
What I did was starting the app from intelij and then pressing home button and open the app again. Every time the app heap was doubled.
Finally I discover when I launch the app from ADB and press the home button and open the app again it doesn't bring back the old activity, it just start a new one. When I pressed finish it starts to cycle through all of them. It's like they are treated as two different intent. So I put android:launchMode="singleTop" on the main activity in manifest and it resolved the problem.
Although it's not the main cause of this problem but if you encountered this check this out before anything. It wasted three or four hours for me.
In a game for Android written in Scala, I have plenty of objects that I want to pool. First I tried to have both active (visible) and non active instances in the same pool; this was slow due to filtering that both causes GC and is slow.
So I moved to using two data structures, so when I need to get a free instance, I just take the first from the passive pool and add it to the active pool. I also fast random access to the active pool (when I need to hide an instance). I'm using two ArrayBuffers for this.
So my question is: which data structure would be best for this situation? And how should that (or those) specific data structure(s) be used to add and remove to avoid GC as much as possible and be efficient on Android (memory and cpu constraints)?
The best data structure is an internal list, where you add
var next: MyClass
to every class. The non-active instances then become what's typically called a "free list", while the active ones become a singly-linked list a la List.
This way your overhead is exactly one pointer per object (you can't really get any less than that), and there is no allocation or GC at all. (Unless you want to implement your own by throwing away part or all of the free list if it gets too long.)
You do lose some collections niceness, but you can just make your class be an iterator:
def hasNext = (next != null)
is all you need given that var. (Well, and extends Iterator[MyClass].) If your pool sizes are really quite small, sequential scanning will be fast enough.
If your active pool is too large for sequential scanning down a linked list and elements are not often added or deleted, then you should store them in an ArrayBuffer (which knows how to remove elements when needed). Once you remove an item, throw it on the free list.
If your active pool turns over rapidly (i.e. the number of adds/deletes is similar to the number of random accesses), then you need some sort of hierarchical structure. Scala provides an immutable one that works pretty well in Vector, but no mutable one (as of 2.9); Java also doesn't have something that's really suitable. If you wanted to build your own, a red-black or AVL tree with nodes that keep track of the number of left children is probably the way to go. (It's then a trivial matter to access by index.)
I guess I'll mention my idea. The filter and map methods iterate over the entire collection anyway, so you may as well simplify that and just do a naive scan over your collection (to look for active instances). See here: https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/TraversableLike.scala
def filter(p: A => Boolean): Repr = {
val b = newBuilder
for (x <- this)
if (p(x)) b += x
b.result
}
I ran some tests, using a naive scan of n=31 (so I wouldn't have to keep more than a 32 bit Int bitmap), a filter/foreach scan, and a filter/map scan, and a bitmap scan, and randomly assigning 33% of the set to active. I had a running counter to double check that I wasn't cheating by not looking at the right values or something. By the way, this is not running on Android.
Depending on the number of active values, my loop took more time.
Results:
naive scanned a million times in: 197 ms (sanity check: 9000000)
filter/foreach scanned a million times in: 441 ms (sanity check: 9000000)
map scanned a million times in: 816 ms (sanity check: 9000000)
bitmap scanned a million times in: 351 ms (sanity check: 9000000)
Code here--feel free to rip it apart or tell me if there's a better way--I'm fairly new to scala so my feelings won't be hurt: https://github.com/wfreeman/ScalaScanPerformance/blob/master/src/main/scala/scanperformance/ScanPerformance.scala
I found these code may case memory leak on android 2.1
SoundPool soundPool = new SoundPool(10, 7, 0);
...
...
soundPool = null;
every time after the execution, the MAT pluging tells that two String objects of "android:unnamed_thread" are added to the heap of the process. is that an issue?
did you try to run soundPool.release() instead of soundPool = null?
I see two possibilities (there may well be more).
The first (most likely) is true of all Java objects: just because you set the reference to null doesn't automatically mean that the object behind it will be garbage-collected.
If a SoundPool object itself contains a reference to the two thread objects, none of the three will necessarily be GC'ed until space is required (although that depends, of course, on how aggressive your collector is).
The second (less likely) is that Android may be smart enough to cache thread (or even SoundPool) objects in case they need to be used again. They may nave done this as a performance optimisation if object creation is more expensive than object re-cycling.
In that case, they would still have a reference to the objects somewhere in a cache and they wouldn't be considered eligible for garbage collection.