Android Garbage collector Runs on Main Thread? - android

Example:
Lets say ideally that object is garbage collectable (activity changed orientation and strong reference to object lost) but not yet disposed. So line 2 will return true. Is there any way that object get disposed while execution is on line 3? Or it wait until it finishes?
new Thread {
WeakReference item= new WeakReference(object);
void method(){
2 if(item.get()!=null)
3 item.get().getName();
}
}

If you have strong reference to an object then that object is not eligible for GC.
There is no way strong referenced object will get disposed in code between null check and next line... or any other line as long as you can access that object reference. Only if you set that object reference to null, or you assign another object to that reference, previous object can be garbage collected if there are no other references pointing to it.
On the other hand, when you are dealing with weak references (of any kind) first you have to take strong reference out of weak reference wrapper and then you can safely use that strong reference further on (after you check it is not null, of course). If you don't take strong reference, object in weak wrapper can vanish at any time.
Wrong usage - object can be collected between null check and getName call
if(item.get()!=null)
item.get().getName();
Correct usage - taking strong reference for further processing
Object object = item.get();
if(object!=null)
object.getName();

First of all Garbage Collector does not run on what you think as your proccess's main thread.
When looking from Operating System's prospective, GC may run either in main thread of the virtual machine that runs your application. Or it can run on a new thread.
But from Java prospective, GC does not run on any of your application's thread. The thread that run GC is neither your Java main thread nor a Java thread accessible to you.
From the prospective of your Java code, the main thread and all other thread are stopped (removed from scheduler) while GC runs. This is not always true though. But that is up to the VM implementation. But you must always assume that all your Java threads, including main thread are stopped while GC runs.
So, to precisely answer your question, **
Yes, your week reference can become null in the second line.
**
Your code can get a NullPointerException in line three.
Because line 2 and 3 are two seperate non antomic operations. It is possible that GC can cick in after executing line 2 , stop execution of all your threads, do garbage collection , and then resume all your threads causing a NullPointerException to occur at line 3.

Related

Xamarin Android garbage collection algorithm

I am reading the Xamarin.Android garbage collection docs about helping the GC perform better by reducing referenced instances.
The section begins by saying:
Whenever an instance of a Java.Lang.Object type or subclass is scanned during the GC, the entire object graph that the instance refers to must also be scanned. The object graph is the set of object instances that the "root instance" refers to, plus everything referenced by what the root instance refers to, recursively.
...which I understand.
It then goes to show a custom class inheriting from the standard Activity class. This custom activity class has a field that is a list of strings which is initialized in the constructor to have 10,000 strings. This is said to be bad because all 10,000 instances will have to be scanned for reachability during GC. That I also understand.
The part that I am not clear on, is the recommended fix: it says the List<string> field should be moved to another class that doesn't inherit from Java.Lang.Object and then an instance of that class should be referenced from the activity just like the list was being referenced before.
My question: how does pushing a field deeper into the object graph help the GC when the total number of instances is still 10,000 and the opening paragraph says they will be scanned eventually because the process is recursive?
As a side note, I am also reading up (here) on the SGen GC used by Mono on Android and the object graph traversal process is described as being breadth-first starting with the GC roots. This explains how a 10,000 item list will cause a longer GC pause as each item is checked, but still doesn't explain how moving that list deeper into the graph will help because the GC will eventually scan it as it goes deeper into the graph.
I'll try to explain this the best I can, and I'm nowhere near an expert here so anyone who wants to chime in, please do so.
When we are referring to doing a peer walk, we are locating any roots and traversing the live reference graph to see what is reachable and what is not:
Root Objects:
Objects pointed at by static fields / properties
Objects on the stack of each managed thread
Objects that have been passed into native APIs
Basically you then have to deal with two managed GCs. We'll call them the Xamarin GC and the Android GC for reference.
Xamarin.Android has peer objects which are used to reference the native Java objects known in the Android JVM. They implement a core interface:
namespace Android.Runtime
{
public interface IJavaObject : IDisposable
{
// JNI reference to the Java object it is wrapping.
// Also known as a pointer to the JVM object
public IntPtr Handle { get; set; }
...
}
}
Whenever we have an object with IJavaObject inherited, it will keep a strong reference via that JNI handle above to ensure it is kept alive as long as the managed object is alive.
Think of it this way:
IJavaObject -> IntPtr Handle -> Java Object
In GC terms, it would be represented as the following:
Allocated and collected by Xamarin GC -> GC Root -> Allocated and collected by Android GC
We then have a GC process in Xamarin.Android:
When the GC runs, you can see that it will replace a strong JNI handle with a weak reference and then invoke the Android GC which will collect our Java object. Because of this, the peers are scanned for any relationships to ensure that they are mirrored in the JVM. This keeps these objects from being collected prematurely.
Once this happens, we run the Android GC and when it's finished it will walk through the peer objects and check the weak references.
If an object is gone, we collect it on the C# side
If an object still exists, then we change the weak reference back to a strong JNI handle
Thus this graph needs to be checked and updated each time a GC runs on peer objects. That's why it's much slower for these wrapper type objects because the entire object graph has to be scanned starting at the peer object.
So when there are significant object graphs that our peer object uses, we can help out the GC process by moving the storage of the references outside the peer class. This is usually done by rooting our reference independent of the peer. And since it's not stored as a field, the GC will not try to do a relationship walk on the object graph.
As noted earlier, this isn't a huge issue to worry about until you notice long GCs. You can then use this as a solution.
Image Credit: Xamarin University(https://www.xamarin.com/university)

Missing Virtual Destructor Memory Effects

According to the standard, polymorphism with a missing virtual destructor leads to undefined behavior. In practice, it really leads to the destructor for the derived class not being called when the parent class is deleted. However, does it also lead to memory leaks in any common compilers/systems? I'm particularly interested in g++ on Android/Linux.
Specifically, I'm referring to whether the deletion of memory for the derived class will somehow leak. Consider:
class Base {}
class Derived {
int x;
}
If I delete a Base* to a Derived, will I leak 4 bytes? Or does the memory allocator already know how many bytes to free based on the allocation?
It certainly can do. Consider:
class A
{
public:
virtual void func() {}
};
class B : public A
{
public:
void func() { s = "Some Long String xxxxxx"; }
private:
std::string s;
// destructor of B will call `std::string` destructor.
};
A* func(bool b)
{
if (b)
return new B;
return new A;
}
...
A* a = func(true);
...
delete a;
Now, this will create a memory leak, as std::string s in the B object is not freed by A::~A - you need to call B::~B, which will only happen if the destructor is virtual.
Note that this applies to ALL compilers and all runtime systems that I'm aware of (which is all the common ones and some not so common ones).
Edit:
Based on the updated actual question: Memory de-allocation happens based on the allocated size, so if you can GUARANTEE that there NEVER is a single allocation happening because of the construction/use of the class, then it's safe to not have a virtual destructor. However, this leads to interesting issues if a "customer" of the base-class can make his/her own extension classes. Marking derived classes as final will protect against them being further derived, but if the base class is visible in a header-file that others can include, then you run the risk of someone deriving their own class from Base that does something that allocates.
So, in other words, in something like a PImpl, where the Impl class is hidden inside a source file that nobody else derives from, it's plausible to have this. For most other cases, probably a bad idea.
A missing destructor will cause undefined behavior specifically because it's implausible for the compiler to know exactly what the side effects might be.
Think of it as the cleanup side of RAII. In that case, if you manage to not clean up despite claiming that you did, side effects might be:
Leaked memory (you allocated something... when do you deallocate it now?)
Deadlocks (you locked something... when do you unlock it now?)
Sockets remaining open (you opened it sometime... but now when do you close it?)
Files remaining open (you opened it sometime... but now when do you flush it?)
Accessing invalid pointers (for example, you updated a pointer to some member... but now when do you unset it?)
Your hard drive gets erased (technically this is a valid answer for any undefined behavior)
This should cause Undefined Behaviour which means it might also cause memory leaks. In 5.3.5/3 (n4296 c++14) for delete you have:
In the first alternative (delete object), if the static type of the object to be deleted is different from its
dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the
static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete
array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

Issue about weakreferences

I have one or two weakreferences in my program.
Just for example:
ClassX myClassX= new ClassX(); //Line 1
WeakReference<ClassX> myWeakClassX = new WeakReference<ClassX>(myClassX); //Line 2
if(myWeakClassX.get() != null) // Line 3
{
//do something with reference //Line 4
}
My question:
How is it ensured that when at line 3 myWeakClassX.get() has a valid reference to an Object, it is also valid at line 4? I can imagine that if you are really unlucky, the GC does his job exactly "between" line 3 and 4. Please bear with me, because i'm relatively new to Android/Java..
Thanks for any explanation.
In Java, first thing to understand is Garbage Collector reclaims memory from objects which are eligible for garbage collection
Question is how is the eligibility defined ?
eligibility is decided based upon which kind of references are pointing to that object.
Why we need Weak Reference ?
If you create a Strong reference to an object, the object cannot be garbage collected. Whereas, A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself.
Issue here
Weak reference isn't strong enough to prevent garbage collection, so you may find (if there are no strong references to the class) that myWeakClassX.get() suddenly starts returning null.
What is the other option ?
Soft Reference
You use a SoftReference when you want the referenced object to stay alive until the host process is running low on memory. The object will not be eligible for collection until the collector needs to free memory. Loosely stated, binding a SoftReference means, "Pin the object until you can't anymore."
This way myWeakClassX.get() will not be null.
Examples of where we can use ?
In any secondary threads where you create a reference to the activity.
WeakReference weakActivity;
//In AsyncTask onPostExecute Method
Activity activity = weakActivity.get();
if (activity != null) {
// do your stuff with activity here
}
If you can referring to an Activity context elsewhere, you can use Weak reference.
While handling bitmap resources in imageview in another thread
http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
If you are creating any Hashmap or any widget to hold any data, you can use Weak reference. http://developer.android.com/reference/java/util/WeakHashMap.html
Usage is unlimited. It is up to the developer to utilize it at right places.
You are correct that during line 3 and 4 the get() operation can return null, as it is supposed to do. You can always copy the reference you get from get() operation into a variable (thus making it strong again) and use it within the if block safely. Because you still have a strong reference, the object will not be garbage collected.
A simple check for null can be:
if(myWeakClassX.get() != null)
{
ClassX myref = myWeakClassX.get();
if(myref != null) {
//use it
}
}
However in-case of activities, having a strong reference does not guarantee that the activity will not be destroyed and although you have a strong reference that is valid, the activity may throw exceptions when you try to use it as it is destroyed.
Example: If you are keep reference for an activity inside some AsyncTask, the activity might get destroyed (i.e orientation change) before AsyncTask runs. And although you will have a reference to it, you will get exceptions when you try to update UI.
That is where you can create a WeakRefernce to activity inside the AsyncTask and if the get() operation start returning null, you will know that the activity was destroyed by whatever reason and not try to use it.

How can a single java thread execute more than one native method at a time?

I am trying to track down a problem in my Android application. This problem causes a crash during garbage collection in the native layer of the code. I'll explain myself.
My application consists merely in java source controlling GUI elements and such and a native library that manages rendering and other performance-critical parts of the application. It features a GLSurfaceView for rendering.
The java layer needs to be able to access and instantiate native objects, so these are exposed to Java through Swig. What Swig does is that in each wrapper class (in Java) it generates a finalize method that will call the native delete operator.
Consider the following pseudo-code:
In C++:
class MyClass {
public:
MyClass () {}
~MyClass ()
{
print("deleting MyClass instance");
print("doing 1");
do1();
print("doing 2");
do2();
print("doing 3");
do3();
print("instance deleted");
}
};
This is pseudo code meaning that for example "print" stands for print in android logcat I was just Keeping It Simply Stupid ;) .
What puzzles me is that when the garbage collector runs, and calls the destructors in some cases I can find the output interleaved between multiple destructors (as if they were being deleted concurrently). In this example case it could be :
deleting MyClass instance
doing 1
deleting MyClass instance
doing2
doing1
doing2
deleting MyClass instance
doing3
doing3
instance deleted
doing1
doing2
instance deleted
doing3
instance deleted
While at the same time logcat clearly states that these messages originate from the same thread (the finalizer thread).
Hence my question: "How can a single thread be executing multiple native calls at the same time ?"
Does the native destructor call back into the VM?

Android: static field set to null

I have an Activity with a private static field. And that static field is set to null when I turn the screen. Of course, one would guess that Android kills the process, but I'm sure it does not. But let's begin from the beginning.
There is a JNI library whose functions may be called from only one thread. From Java, the library functions are visible as native methods of an object (by the way, only one instance of that object is meaningful, there will be only one instance of the library with its static structures). The library object is used via a wrapper, a Java layer providing read/write access locks. The activity has a private static field referencing that wrapped library object. The library performs a long operation on a separate thread.
The singleton creation was like the following. Since all activities are created on the same UI thread, in onCreate() I just checked if the field is null and if it is null, created a wrapped library object. There was no problem -- at least, on Android 2.x.
Now, on Android 4, the following happens: I start a long operation and turn the screen.
The activity is re-created, the savedInstanceState parameter in onCreate() is not null, but that private static field is null.
Now, a new library object is created, then a new wrapper is created with its new read/write lock, and then a library operation is invoked... of course, the library is still busy with the request initiated before turning the screen, the new read/write lock does not protect the old library, data get corrupt and everything crashes.
I have heard that a remedy to this would be to keep the reference not as a static field but as an instance field of the Application.
Now, the question is:
WHY? What the hell is going on? Do I have to rewrite all singletons?

Categories

Resources