Static references are cleared--does Android unload classes at runtime if unused? - java

I have a question specific to how the classloading / garbage collection works in Android. We have stumbled upon this issue a few times now, and as far as I can tell, Android behaves different here from an ordinary JVM.
The problem is this: We're currently trying to cut down on singleton classes in the app in favor of a single root factory singleton which sole purpose is to manage other manager classes. A top level manager if you will. This makes it easy for us to replace implementations in tests without opting for a full DI solution, since all Activities and Services share the same reference to that root factory.
Here's how it looks like:
public class RootFactory {
private static volatile RootFactory instance;
#SuppressWarnings("unused")
private Context context; // I'd like to keep this for now
private volatile LanguageSupport languageSupport;
private volatile Preferences preferences;
private volatile LoginManager loginManager;
private volatile TaskManager taskManager;
private volatile PositionProvider positionManager;
private volatile SimpleDataStorage simpleDataStorage;
public static RootFactory initialize(Context context) {
instance = new RootFactory(context);
return instance;
}
private RootFactory(Context context) {
this.context = context;
}
public static RootFactory getInstance() {
return instance;
}
public LanguageSupport getLanguageSupport() {
return languageSupport;
}
public void setLanguageSupport(LanguageSupport languageSupport) {
this.languageSupport = languageSupport;
}
// ...
}
initialize is called once, in Application.onCreate, i.e. before any Activity or Service is started. Now, here is the problem: the getInstance method sometimes comes back as null -- even when invoked on the same thread! That sounds like it isn't a visibility problem; instead, the static singleton reference hold on class level seems to actually have been cleared by the garbage collector. Maybe I'm jumping to conclusions here, but could this be because the Android garbage collector or class loading mechanism can actually unload classes when memory gets scarce, in which case the only reference to the singleton instance will go away? I'm not really deep into Java's memory model, but I suppose that shouldn't happen, otherwise this common way of implementing singletons wouldn't work on any JVM right?
Any idea why this is happening exactly?
PS: one can work around this by keeping "global" references on the single application instance instead. That has proven to be reliable when one must keep on object around across the entire life-time of an app.
UPDATE
Apparently my use of volatile here caused some confusion. My intention was to ensure that the static reference's current state is always visible to all threads accessing it. I must do that because I am both writing and reading that reference from more than one thread: In an ordinary app run just in the main application thread, but in an instrumentation test run, where objects get replaced with mocks, I write it from the instrumentation thread and read it on the UI thread. I could have as well synchronized the call to getInstance, but that's more expensive since it requires claiming an object lock. See What is an efficient way to implement a singleton pattern in Java? for a more detailed discussion around this.

Both you (#Matthias) and Mark Murphy (#CommonsWare) are correct in what you say, but the gist seems lost. (The use of volatile is correct and classes are not unloaded.)
The crux of the question is where initialize is called from.
Here is what I think is happening:
You are calling initialize from an Activity *
Android needs more memory, kills the whole Process
Android restarts the Application and the top Activity
You call getInstance which will return null, as initialize was not called
Correct me if I'm wrong.
Update:
My assumption – that initialize is called from an Activity * – seems to have been wrong in this case. However, I'll leave this answer up because that scenario is a common source of bugs.

I have never in my life seen a static data member declared volatile. I'm not even sure what that means.
Static data members will exist until the process is terminated or until you get rid of them (e.g., null out the static reference). The process may be terminated once all activities and services are proactively closed by the user (e.g., BACK button) and your code (e.g., stopService()). The process may be terminated even with live components if Android is desperately short on RAM, but this is rather unusual. The process may be terminated with a live service if Android thinks that your service has been in the background too long, though it may restart that service depending on your return value from onStartCommand().
Classes are not unloaded, period, short of the process being terminated.
To address the other of #sergui's points, activities may be destroyed, with instance state stored (albeit in RAM, not "fixed storage"), to free up RAM. Android will tend to do this before terminating active processes, though if it destroys the last activity for a process and there are no running services, that process will be a prime candidate for termination.
The only thing significantly strange about your implementation is your use of volatile.

Static references are cleared whenever the system feels like it and your application is not top-level (the user is not running it explicitly). Whenever your app is minimized and the OS wants some more memory it will either kill your app or serialize it on fixed storage for later use, but in both cases static variables are erased.
Also, whenever your app gets a Force Close error, all statics are erased as well. In my experience I saw that it's always better to use variables in the Application object than static variables.

I've seen similar strange behaviour with my own code involving disappearing static variables (I don't think this problem has anything to do with the volatile keyword). In particular this has come up when I've initialized a logging framework (ex. Crashlytics, log4j), and then after some period of activity it appears to be uninitialized. Investigation has shown this happens after the OS calls onSaveInstanceState(Bundle b).
Your static variables are held by the Classloader which is contained within your app's process. According to google:
An unusual and fundamental feature of Android is that an application
process's lifetime is not directly controlled by the application
itself. Instead, it is determined by the system through a combination
of the parts of the application that the system knows are running, how
important these things are to the user, and how much overall memory is
available in the system.
http://developer.android.com/guide/topics/processes/process-lifecycle.html
What that means for a developer is that you cannot expect static variables to remain initialized indefinitely. You need to rely on a different mechanism for persistence.
One workaround I've used to keep my logging framework initialized is for all my Activities to extend a base class where I override onCreate and check for initialization and re-initialize if necessary.
I think the official solution is to use the onSaveInstanceState(Bundle b) callback to persist anything that your Activity needs later, and then re-initialize in onCreate(Bundle b) when b != null.
Google explains it best:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html

Related

Singleton returns null when accessed by threads

As the title states I'm trying to troubleshoot an issue where some threads which read data from a Singleton get a null value. My investigation into our logs read as though its a concurrency issue.
The Singleton is defined as follows:
#Singleton
public class StaticDatabaseEntries {
private static final Map<String,Thing> databaseEntries = new HashMap<>();
#Lock(LockType.READ)
public Thing getThing(String index) {
return databaseEntries.get(index);
}
}
At first I was under the impression that only one element within the data was corrupted as access to the same item is repeatededly returning null. Further access to debug entries show that the issue appears isolated to a specific thread. It's as though once whatever occurs that induces the null return on a thread continues to do so but only on the affected thread.
An earlier version of this class did not apply the LockType.READ so per the specification a LockType.WRITE is assumed. I deployed an update with the correct lock to enable concurrent read. This did not improve the situation.
The data is loaded into the HashMap from a database upon deployment and remains unchange for the duration. Since the class isn't tagged with #Startup the application instead uses a context listener to trigger the loading of the entries from database.
With threads primarily performing a read activity I don't believe a switch to ConcurrentHashMap is benficial. I am considering removing the static final portion as it seems unnecessary when the container is managing concurrent access and the singleton lifecycle. I have experienced side effects when the container cannot subclass/proxy things which are marked as final in EJBs.
The other possibility I've considered is there is some manner of bug in the container software. This is running on a older Java 1.7 and JBOSS 6 EAP. Worst case I'll have to forego the singleton pattern and instead load the entries from the database on demand.
In general: If you work with threads, read activity can cause problems, if you are calling an object method, that isn't thread-save! This is exactly what often leads to undetectable errors in larger projects.
HashMap isn't thread-safe!
You should switch to ConcurrentHashMap.
For further details, have a look at this article: https://www.baeldung.com/java-concurrent-map

Handling common code between different activities, fragments, tasks, etc

I have quite some (not too much, but quite some) experience with Java and object-oriented programming in other languages, but am fairly new to Android and my understanding of all its different classes is at best described as limited (more realistic would be confused).
I'm creating an application that for now consists of one activity and a widget. One of its functionality will be fetching some data from the internet. This data will only change every day on some arbitrary moment, so there's no need to fetch this data every time you start the app or look at the widget.
My problem is that I'd like to have one method to fetch the data and store it in shared preferences, together with the update time (so that it's only updated once a day). This method has to be accessible from the widget and the activity.
Normally I would simply create some class with a static method to do this. However, to access the shared preferences you need a Context. I can come up with two ways:
Option 1: static method, Context as parameter
public class MyClass {
public static String fetchData(Context context) {
return // ...
}
}
Option 2: singleton
public class MyClass {
private static MyClass instance = null;
private Context context;
public MyClass(Context context) {
this.context = context;
}
public String fetchData() {
return ...;
}
public static MyClass getInstance(Context context) {
if (instance == null)
instance = new MyClass(context);
return instance;
}
public static MyClass getInstance() {
return instance;
}
}
Now I would call it with MyClass.getInstance(getActivity()).fetchData() the first time, and after that MyClass.getInstance().fetchData().
My question
Is either of these preferred over the other, and if so, why? Or is there another, better, way to do this kind of thing? Or does it depend on the situation (and in that case, on what precisely?)?
Later, I may have more of these methods. Since the Context is something that normally doesn't change, I thought a singleton may be useful here because after the first instantiation you don't need to give a context anymore.
Option 1 is ok to use almost all the time. Option 2 is dangerous because you are keeping a reference to a Context. if the Context is of type Activity you can have memory leaks - your Referenced Activity will not be GC
If you are using option 2 make sure you are using Application Context.
To init the singleton do something like:
getInstance(myActivity.getApplicationContext())
option 1 is much better if the method is a utility method - does something and does not need to change it's state after the method has returned.
first of all you are not keeping a reference to Context. also you don't need to hold a singleton in the memory. Last Static methods are efficient.
Use option 2 if you are using the Singleton all the time and recreating objects during the process (Picasso, RetroFit are good examples for the need of Singleton)
A good example of when to use a Singleton is Android Volley library. It's also relevant to fetching data from remote so have a look
In essence, neither of your approaches are required for what you initially describe...
I'm creating an application that for now consists of one activity and a widget. One of its functionality will be fetching some data from the internet. This data will only change every midnight, so there's no need to fetch this data every time you start the app or look at the widget.
So what exactly is going to be responsible for the daily download and how is it going to be triggered? Neither an Activity nor an App Widget is suitable.
Add a few bits and pieces - use AlarmManager to create a repeating alarm set for around midnight (it won't be exact but normally within a few seconds). Have the alarm trigger a broadcast which is received by a BroadcastReceiver and then have the receiver start an IntentService to download and save what's needed.
It's a win-win scenario. The alarm will be fired regardless of whether your app is 'running' or not (or whether the phone is asleep or not). The receiver will be triggered and the IntentService uses its own worker thread so no need to worry about any problems with running network code on the main/UI thread. Also, an IntentService has a Context which can be used to access SharedPreferences and will shut itself down after it has done its work.

Using static method and variables in java web application

I have a search box in the header of my web application and use autocomplete to help users find books by author's name or book's title. On user input, oninput() function calls servlet FindBooks through ajax. FindBooks servlet calls static method suggest() of class SuggestionBook which returns array of books matching input string.
FindBooks.java
JSONArray books = SuggestionBook.suggest(inputString);
out.print(books);
SuggestionBook.java
private static boolean isTernaryEmpty = true;
private static Ternary ternary;
private static void fillTernary() {
// fills ternary search tree with data.
isTernaryEmpty = false;
}
public static JSONArray suggest(String searchString) {
if(isTernaryEmpty) {
fillTernary();
}
return ternary.find(searchString);
}
I have used static methods in class SuggestionBook.java, so as to avoid loading data for each session of application. So it will be loaded only once and then can be shared by different sessions. But since there is only one copy of static method and all sessions use the same static method to fetch data. Do they have to wait while some other session is using the method or it can be accessed simultaneously by all sessions ? If Yes, does it affect the performance of the application. If No, how this concurrent access of a single copy is managed by JVM ? Lastly, as per my understanding data will stay in the memory as long as class SuggestionBook is not garbage collected. Is it a right approach to use data structures as class variables than instance variables, as they will block available memory for longer time.
Do they have to wait while some other session is using the method or it can be accessed simultaneously by all sessions ?
No they don't have to wait and yes they can be accessed simultaneously.
Accessing the same object from multiple sessions simultaneously can be a
problem but does not have to be. If for example two sessions perform
simultaneous access to an object without changing its state that would be
fine. If they do change the state and the state transition involves instable
intermediate states a problem could arise.
If two threads are running the same method at the same time they will both have their code pointers pointing at that method and have their own copies of arguments and local variables on their stacks. They will only interfere with each other if the things on their stacks point to the same objects on the heap.
If Yes, does it affect the performance of the application. If No, how this concurrent access of a single copy is managed by JVM ?
Memory in java is split up into two kinds - the heap and the stacks. The heap is where all the objects live and the stacks are where the threads do their work. Each thread has its own stack and can't access each others stacks. Each thread also has a pointer into the code which points to the bit of code they're currently running.When a thread starts running a new method it saves the arguments and local variables in that method on its own stack. Some of these values might be pointers to objects on the heap.
Lastly, as per my understanding data will stay in the memory as long as class SuggestionBook is not garbage collected. Is it a right approach to use data structures as class variables than instance variables, as they will block available memory for longer time.
Since you're using servlet, a single instance of servlet is created only once on webapp's startup and shared among all requests. Static or not, every class/instance variable is going to be shared among all requests/sessions.
There will be only a single instance of the Servlet, and an instance variable will act like a static variable. Therefore, rather than requiring people to know about the single instance (since many people do not) by making the variable static rather than instance, it removes any confusion in the usage. Therefore the intent of the variable is clearer and less likely to be misunderstood. So yeah its is not a bad approach by usability.
You can make suggest method as synchronized and it will work. As only the first called will fill the data in tree and the subsequent calls just read it.
But if you synchronize suggest method, every thread that calls suggest will be synchronized and this is unnecessary since the first call has already filled the tree.
Solution 1) Create a static block and initialize the tree in that. So that way the tree is initialized as soon as the class is loaded.
Solution 2) make "fillTernary" method as synchronized and inside the method initialize the tree only if it is not initialised i.e if(isTernaryEmpty). Please note that the if condition is required in both the methods which is to prevent multiple threads from initializing at the same time.

is it possible for Android VM to garbage collect static variables without killing the whole Android application?

(Title is misleading since garbage collectors collect only objects, but I found this title more straightforward)
Suppose I have an Android application with a static variable named "userid" inside a class called Global (which is null at initialization time).
If I set "userid" variable to some value duing Android application lifecycle, say Global.userid = "myid", is it possible for this variable to become null while Android application is still alive?
In other words, is it possible for Android VM to unload Global class and "kill" this global static variable due to low-memory issue without killing the whole Android application?
I am worried about the situation that userid becomes suddenly null while application is running (due to low memory issue), therefore crashing the whole app.
Edit
I was misunderstanding some concepts (between application process vs activities). Thanks for all answers!
If I set "userid" variable to some value duing Android application lifecycle, say Global.userid = "myid", is it possible for this variable to become null while Android application is still alive?
If you set it to null yourself, yes.
In other words, is it possible for Android VM to unload Global class and "kill" this global static variable due to low-memory issue without killing the whole Android application?
For normal cases, no.
If you play around with custom classloaders, it is conceivable that there may be scenarios in which classes get unloaded (and hence any static data members on them go poof) -- I seem to recall there was discussion about this scenario, but I forget the conclusion. However, very few apps should be messing around with custom classloaders.
I am worried about the situation that userid becomes suddenly null while application is running (due to low memory issue), therefore crashing the whole app.
That should not happen.
What can happen is that the user is in your app, leaves the app via HOME (or a notification, or an incoming call, or the recent-tasks list, etc.), then later returns to your app via the recent-tasks list. If your process had been terminated during the time it was not in the foreground, your static data member will be null when your activity is started up from the recent-tasks list. Since the activity the user returns to may not necessarily be your launcher activity, your app may behave as though the static data member spontaneously turned null, even though it was because your process had been terminated and restarted.
This is one of several reasons why static data members need to be used very carefully.
If you are making the variable static so that you can access it from anywhere in your app without creating a new instance of the class every time I believe this is a good candidate for the Singleton pattern.
String userid = Global.getInstance().userid;

What is the best equivalent of a main() function for an Android app?

I've searched everywhere a manner to have the equivalent of a main() function (yes function not method) inside a Android application but failed...
Typically what I would want to do is:
void main()
{
// do some really nice initialisations stuff here
// ... let the app does his life, I really don't care
// do some final stuff here before leaving
}
The nearest approach I've seen so far is to use a SplashScreen and override the OnCreate() method. The problem is that is not acceptable from my point of view.
Why? Because a SplashScreen is nothing than an Activity tagged as a LAUNCHER.
That makes it to appear in the apps list, thing I don't want when I develop an app widget.
Furthermore, where to place my code just before the app destroy? In the onDestroy() method?
No, once again, this is not reliable. Android can decide to delete my instance whereas the application is still running.
Well, in fact, I take for principle that every components of my app are running in the same process since I don't mention explicitely in the Manifest that I wan't a component to run in its own process.
In the case of an app widget, I've placed my init code on the first call of onUpdate() method. I think it's a good bet. Then this app widget (AppWidgetProvider more precisely) is in charge to launch any activity as its will.
The "DataBase" for all the app is defined in a separate Singleton like this:
public class MyDataBase {
public static MyDataBase getInstance() {
if (instance_ == null)
instance_ = new DataBase();
return instance_;
}
public void load();
public void save();
static MyDataBase instance_ = null;
public int myInt;
public String myString;
public Object myObject;
etc..
}
With this Singleton I'm sure at least, its lifecycle is the same as the entire app itself.
To back with that AppWidgetProvider, I have to trick a little. Indeed, Android can decide to delete its instance whereas some other activities are still on place and the process is still running. So for example, systematically loading my DataBase in the first call of the OnUpdate() is unnecessary and overkill. What I do is having a static boolean value that indicates if the DataBase have been loaded for the lifecycle of this process or not.
Thus, the AppWidgetProvider can be instanciated tons of time, as long as the Singleton DataBase persists (so the process), it will not reload the DataBase each time, got it?
(yes difficult to be clear...)
About the cleanup code of the app, I thought to override the finalize() method of my DataBase Singleton, but well, I'm really not sure it's a good idea since the moment of the call of this method is totally unpredictable. I suppose it would be called if you suddently power off your Android, but well I'm not sure of anything here, thus so far, I didn't found a solution for that part.
Any comment or something less tricky that what I currently do is welcome.
Thanks.
onResume() is the function that will be invariably reached before starting you app, so you could either put the 'main' code in the onCreate() method or the onResume().
onPause() is ALWAYS called before destroying the app, either by the user or the OS.
There is great explanation regarding the lifecycle in the Android documentation:
http://developer.android.com/training/basics/activity-lifecycle/starting.html
For the initialisation you can over-ride the onCreate method of the Application class:
Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created. Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity, service, or receiver in a process. If you override this method, be sure to call super.onCreate()
Termination is harder to deal with. You'll probably have to monitor each component of your application separately. If you are targeting API level 14 or later you can use Application.registerActivityLifecycleCallbacks to help with this.
The nearest approach I've seen so far is to use a SplashScreen and
override the OnCreate() method. The problem is that is not acceptable
from my point of view. Why? Because a SplashScreen is nothing than an
Activity tagged as a LAUNCHER.
It's because Android is formed with several activities and those activities have life cycles. So every activities start from onCreate() then finishes at onDestroy().
http://developer.android.com/training/basics/activity-lifecycle/starting.html
That makes it to appear in the apps list, thing I don't want when I
develop an app widget. Furthermore, where to place my code just before
the app destroy? In the onDestroy() method? No, once again, this is
not reliable. Android can decide to delete my instance whereas the
application is still running.
In a scenario that user presses home button to exit from your app, your current activity is more likely to invoke onPause() method (only when the activity has no other processes to finish). However, when user force closes (terminates) your whole application by ending process. Then you don't have to worry about invoking any methods or what so ever because Android itself will close anything related to your application automatically.
To back with that AppWidgetProvider, I have to trick a little. Indeed,
Android can decide to delete its instance whereas some other
activities are still on place and the process is still running. So for
example, systematically loading my DataBase in the first call of the
OnUpdate() is unnecessary and overkill. What I do is having a static
boolean value that indicates if the DataBase have been loaded for the
lifecycle of this process or not. Thus, the AppWidgetProvider can be
instanciated tons of time, as long as the Singleton DataBase persists
(so the process), it will not reload the DataBase each time, got it?
(yes difficult to be clear...)
The example you have posted for singleton database connection is not bad I think, but there are better ways to get the job done cleanly and more effectively. For example hibernate framework connection pooling

Categories

Resources