Thursday, July 26, 2012

What's happening in the JVM level when you concatenate the Strings?


  Have you ever been told by someone about concatenate Strings in Java? Of course, there are many ways to do it but, what is the difference between each approach?

  In this blog post, I disassemble the example Java bytecodes (.class files) into Jasmin (simple assembler-like syntax with JVM instruction set). Each example demonstrates the different way to concatenate Strings(but not cover all the ways that exist in the world ^^).

Lets' disassemble and see what will be happened in the JVM level !

Note: I'm using JasminParser as a disassembler tool.


·         Concatenate Strings using '+' sing.

Java code

public void concatStrings(){
String a = "Hello";
String b = "Johnny";
String c = "Dew";

String result = a + b + c;
}

Jasmin

.method public concatStrings()V
.limit stack 3
.limit locals 5
.var 0 is this Lcom/crack/java/StringConcat; from Label0 to Label1
.var 1 is a Ljava/lang/String; from Label2 to Label1
.var 2 is b Ljava/lang/String; from Label4 to Label1
.var 3 is c Ljava/lang/String; from Label6 to Label1
.var 4 is result Ljava/lang/String; from Label1 to Label1

Label0:
ldc "Hello"
astore_1
Label2:
ldc "Johnny"
astore_2
Label4:
ldc "Dew"
astore_3
Label6:
new java/lang/StringBuilder
dup
aload_1
invokestatic java/lang/String/valueOf(Ljava/lang/Object;)Ljava/lang/String;
invokespecial java/lang/StringBuilder/<init>(Ljava/lang/String;)V
aload_2
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
aload_3
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
astore 4
Label1:
return

.end method

When concatenate String using '+' sign in one statement, Java compiler will translate it to 
a StringBuilder operations.

·         Concatenate Strings using shortcut assignment operator (+=).

Java code

public void concatStrings(){
String a = "Hello";
String b = "Johnny";
String c = "Dew";

String result = null;
result += a;
result += b;
result += c;

}

Jasmin

.method public concatStrings()V
.limit stack 3
.limit locals 5
.var 0 is this Lcom/crack/java/StringConcatShortcutAssignmentOperator; from Label0 to Label1
.var 1 is a Ljava/lang/String; from Label2 to Label1
.var 2 is b Ljava/lang/String; from Label4 to Label1
.var 3 is c Ljava/lang/String; from Label6 to Label1
.var 4 is result Ljava/lang/String; from Label8 to Label1

Label0:
ldc "Hello"
astore_1
Label2:
ldc "Johnny"
astore_2
Label4:
ldc "Dew"
astore_3
Label6:
aconst_null
astore 4
Label8:
new java/lang/StringBuilder
dup
aload 4
invokestatic java/lang/String/valueOf(Ljava/lang/Object;)Ljava/lang/String;
invokespecial java/lang/StringBuilder/<init>(Ljava/lang/String;)V
aload_1
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
astore 4

new java/lang/StringBuilder
dup
aload 4
invokestatic java/lang/String/valueOf(Ljava/lang/Object;)Ljava/lang/String;
invokespecial java/lang/StringBuilder/<init>(Ljava/lang/String;)V
aload_2
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
astore 4

new java/lang/StringBuilder
dup
aload 4
invokestatic java/lang/String/valueOf(Ljava/lang/Object;)Ljava/lang/String;
invokespecial java/lang/StringBuilder/<init>(Ljava/lang/String;)V
aload_3
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
astore 4
Label1:
return

.end method

When concatenate Strings using "+=" sign, the one "+=" called, the one StringBuilder will be created.

·         Concatenate Strings using StringBuilder.

Java code

public void concatStrings(){
String a = "Hello";
String b = "Johnny";
String c = "Dew";

StringBuilder builder = new StringBuilder(a);
builder.append(b);
builder.append(c);

String result = builder.toString();
}

Jasmin

.method public concatStrings()V
.limit stack 3
.limit locals 6
.var 0 is this Lcom/crack/java/StringConcatStringBuilder; from Label0 to Label1
.var 1 is a Ljava/lang/String; from Label2 to Label1
.var 2 is b Ljava/lang/String; from Label4 to Label1
.var 3 is c Ljava/lang/String; from Label6 to Label1
.var 4 is builder Ljava/lang/StringBuilder; from Label8 to Label1
.var 5 is result Ljava/lang/String; from Label1 to Label1

Label0:
ldc "Hello"
astore_1
Label2:
ldc "Johnny"
astore_2
Label4:
ldc "Dew"
astore_3
Label6:
new java/lang/StringBuilder
dup
aload_1
invokespecial java/lang/StringBuilder/<init>(Ljava/lang/String;)V
astore 4
Label8:
aload 4
aload_2
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
pop
aload 4
aload_3
invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;
pop
aload 4
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
astore 5
Label1:
return

.end method

Using StringBuilder is a straightforward way, what are we doing in the Java code will be mostly reflected the operations in the JVM level.


  This blog post is just a result from my curiousness, I just need to know what will be happened in the JVM level when concatenate the Strings in various ways. About the performance of each approach, the results are explicitly answer to this question. So, these are your choices.

Tuesday, July 3, 2012

Displaying Bitmaps Efficiently in Android



Before read this blog post, I highly recommend you to read the original article (Display Bitmaps Efficiently) from Android Developer website first. This is just my summary and diagrams depict the ideas from the original article.


To load Bitmap into memory in an efficient way, you will need to do 2 steps.

  1. Read Bitmap dimensions.
  2. Load a scaled down version into memory.

Here is a flowchart depicts the step to load Bitmap in an efficient way described in the Android Training document.

Fig.1 Steps to load Bitmap.


Processing Bitmaps Off the UI Thread

Processing Bitmap should be done in the worker Thread. The topic "Processing Bitmaps off the UI Thread" describes and show how to process Bitmap using AsyncTask. In the tutorial, each ImageView is referred using WeakReference inside the BitmapWorkerTask. Below is the diagram showing the relationship between BitmapWorkerTask and ImageView from the tutorial.


Fig.2 Relationship between BitmapWorkerTask and ImageView from the tutorial.

The interesting point from this topic is the way to handle concurrency issue. Using AsyncTask to process Bitmaps inside GridView or ListView  can cause ImageView to display wrong image when user scrolls the View. The idea to fix this problem is simple, when got ImageView from the adapter callback, simply check that this ImageView has a BitmapWorkerTask refers to it or not. If there is a BitmapWorkerTask refers to this ImageView then cancel the task before begin process new Bitmap.

The way to check that each ImageView has BitmapWorkerTask refers to it or not is wrapping the BitmapWorkerTask inside the dedicated Drawable subclass (the original article names this class "AsyncDrawable") then set the AsyncDrawable to the ImageView.


Fig.3 Relationship between BitmapWorkerTask, ImageView and AsyncDrawable.

Now when got ImageView from system callback (getView() method), we can check that this ImageView has BitmapWorkerTask refers to it or not, if it is, just simply cancel this task if it is not process the same Bitmap resource with the current request.


Fig.4 Flowchart illustrates the procedure to cancel an exiting BitmapWorkerTask before processing new Bitmap.

Also in BitmapWorkerTask, when processing Bitmap is finished, check if this task is cancelled or the current ImageView is already referred by another task (recycled) before setting image.


Fig.5 Flowchart illustrates the procedure to check current BitmapWorkerTask state before setting new image.


In case of the View components like GridView or ListView, when user scrolls back to the view that already recycled, you have to reprocess the Bitmap for that view again. Reprocess the Bitmap every time user scrolls back to the view cause your UI less responsive. Instead of reprocess, using cache is a better solution.

There are two types of cache: memory cache and disk cache.

For memory cache, LruCache (Least Recently Used Cache) was introduced in Android 3.1 (API level 12) and also available in support package for using in earlier Android version.

For disk cache, an example DiskLruCache class is included inside bitmap sample project and also in Android 4.0 source code (libcore/luni/src/main/java/libcore/io/DiskLruCache.java )

In the case of memory cache, the size of cache is very important. Please see this document for more information.

Tuesday, January 31, 2012

Custom PreferenceActivity

To customize appearance of PreferenceActivity, simply declare XML layout with whatever layout you want to add and also add a ListView with id = @android:id/list which will be replaced by Preference layout. In your PreferenceActivity just call both setContentView(the custom layout) and call addPreferencesFromResource(preference XML);

Wednesday, December 7, 2011

Android AsyncTask - Threading in its lifecycle.

    AsyncTask is one of the great tool in Android development. If you've read in Android document about AsyncTask I'm sure you've known that this class was designed to help you cooperate works between UI Thread and Background (Worker) Thread.


    Since it was born for helping UI Thread to working with Worker Thread, my question is "Is it possible to use AsyncTask to cooperate works between Worker Threads?"


    Yes, I mean start AsyncTask from other Thread (let say Caller Thread) which is not the UI Thread and also maintains all AsyncTask's lifecycle callbacks in Caller Thread.

    For example, if we implement Http component using AsyncTask and the caller of this component is some network interface components that has its own Thread.


    Well, I've done the experiment that was made up to answer my question already and this is source code from my experiment.


    package org.bd.asynctask;

    import android.app.Activity;

    import android.os.AsyncTask;

    import android.os.Bundle;

    import android.os.SystemClock;

    import android.util.Log;

    import android.widget.TextView;

    /**

    * @author Johnny Dew

    * The Goal of this testing is to check that not only the UI

    * Thread that can start and execute in each callback of AsyncTask but,

    * other Worker Thread can start and operates in each callback as well.

    *

    * First AsyncTask will be started by UI Thread directly Second

    * AsyncTask will be started by other Worker Thread.

    */

    public class AndroidAsyncTaskActivity extends Activity {

    private static final String TAG = "AndroidAsyncTaskActivity";

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    Log.v(TAG, String.format("> onCreate # Main Thread ID: %d", Thread

    .currentThread().getId()));

    // 1 use UI Thread

    Log.v(TAG, "> onCreate # Start BdAsyncTask using UI Thread ...");

    BdAsyncTask async1 = new BdAsyncTask();

    async1.execute();

    // 2 use Worker Thread

    new Thread() {

    @Override

    public void run() {

    SystemClock.sleep(3000);

    Log.v(TAG, "> run # Start BdAsyncTask using Worker Thread ...");

    Log.v(TAG, String.format("> run # Worker Thread ID: %d", Thread

    .currentThread().getId()));

    BdAsyncTask async2 = new BdAsyncTask();

    async2.execute();

    }

    }.start();

    }

    private class BdAsyncTask extends AsyncTask {

    private static final String TAG = "BdAsyncTask";

    @Override

    protected void onPreExecute() {

    Log.d(TAG, String.format("> onPreExecute # Thread ID: %d", Thread

    .currentThread().getId()));

    }

    @Override

    protected Void doInBackground(Void... params) {

    Log.d(TAG, String.format("> doInBackground # Thread ID: %d", Thread

    .currentThread().getId()));

    publishProgress(params);

    return null;

    }

    @Override

    protected void onProgressUpdate(Void... progress) {

    Log.d(TAG, String.format("> onProgressUpdate # Thread ID: %d",

    Thread.currentThread().getId()));

    }

    @Override

    protected void onPostExecute(Void result) {

    Log.d(TAG, String.format("> onPostExecute # Thread ID: %d", Thread

    .currentThread().getId()));

    }

    @Override

    protected void onCancelled() {

    Log.d(TAG, String.format("> onCancelled # Thread ID: %d", Thread

    .currentThread().getId()));

    }

    }

    }


    From this source code, I have two instances of BdAsyncTask - which is inherit from AsyncTask class, and first I start my first BdAsyncTask on the UI Thread and then I start my second BdAsyncTask on the Worker Thread. I also print out Thread ID in each lifecycle callbacks in BdAsyncTask to see which Thread is currently running. Here is the output from LogCat.


    Output when execute first BdAsyncTask that's started by UI Thread


    12-07 23:07:18.306: V/AndroidAsyncTaskActivity(16767): > onCreate # Main Thread ID: 1

    12-07 23:07:18.316: V/AndroidAsyncTaskActivity(16767): > onCreate # Start BdAsyncTask using UI Thread ...

    12-07 23:07:18.316: D/BdAsyncTask(16767): > onPreExecute # Thread ID: 1

    12-07 23:07:18.636: D/BdAsyncTask(16767): > doInBackground # Thread ID: 10

    12-07 23:07:19.527: D/BdAsyncTask(16767): > onProgressUpdate # Thread ID: 1

    12-07 23:07:19.537: D/BdAsyncTask(16767): > onPostExecute # Thread ID: 1


    From result above, you can see that the UI Thread got Thread ID 1 and the Worker Thread in BdAsyncTask got Thread ID 10, Worker Thread is running in doInBackground() and the Thread that running in each BdAsyncTask callback is UI Thread. Nothing serious, isn't it?


    Well, let's take a look at the output of the second BdAsyncTask which is started by Worker Thread (Let's call it "Caller Thread")


    12-07 23:07:21.348: V/AndroidAsyncTaskActivity(16767): > run # Start BdAsyncTask using Worker Thread ...

    12-07 23:07:21.348: V/AndroidAsyncTaskActivity(16767): > run # Worker Thread ID: 11

    12-07 23:07:21.348: D/BdAsyncTask(16767): > onPreExecute # Thread ID: 11

    12-07 23:07:21.358: D/BdAsyncTask(16767): > doInBackground # Thread ID: 12

    12-07 23:07:21.389: D/BdAsyncTask(16767): > onProgressUpdate # Thread ID: 1

    12-07 23:07:21.399: D/BdAsyncTask(16767): > onPostExecute # Thread ID: 1


    From the result, the Caller Thread got Thread ID 11 and the Worker Thread in BdAsyncTask got Thread ID 12. Similarly, the Worker Thread still executing in doInBackground() but, Caller Thread only running in onPreExecute() and another callbacks are executed by UI Thread !


    Interesting, isn't it?


    So how about onCancelled() ? Is it executed by UI Thread or Caller Thread?

    Then I modified my code to let Caller Thread cancel BdAsyncTask from executing, now my source code at the Caller Thread stuff should be like this


    // 2 use Worker Thread

    new Thread() {

    @Override

    public void run() {

    SystemClock.sleep(3000);

    Log.v(TAG, "> run # Start BdAsyncTask using Worker Thread ...");

    Log.v(TAG, String.format("> run # Worker Thread ID: %d", Thread

    .currentThread().getId()));

    BdAsyncTask async2 = new BdAsyncTask();

    async2.execute();

    async2.cancel(true);

    }

    }.start();


    From source code above, I've added async2.cancel(true);


    cancel(boolean) will cause AsyncTask to stop execution and invokes onCancelled() then we will see which Thread is going to execute in onCancelled()


    And here is the result from LogCat


    12-07 23:33:17.597: D/BdAsyncTask(17426): > onPreExecute # Thread ID: 11

    12-07 23:33:17.607: D/BdAsyncTask(17426): > onCancelled # Thread ID: 1


    From the result, you can see that Caller Thread still executing in onPreExecute() but onCancelled is executed by the UI Thread.


    According to AsyncTask document it indicate that each AsyncTask lifecycle callback will be executed on the UI Thread but, how about onPreExecute() ? Why it's a Caller Thread that running this method? - document describe that this method is executed by UI Thread ?!?


    Anyway, I've got the answer for my question.

    It doesn't matter which Thread you are using to start AsyncTask, its lifecycle still executed by the UI Thread - except onPreExecute() ?!?.


    So, AsyncTask does its works which is help us cooperate works between Worker Thread and UI Thread. This class is useful when you want to interact with background task from the UI.


    But this is not a good solution for my requirement since I want to interact each "background" components on background Threads - I don't want to use UI Thread to run my works, So instead of using AsyncTask, using other tools like HandlerThread and Handler might be fit with my requirement ;)


NOTE: This experiment was testing on hTC Nexus One running CM-7.1 (Android 2.3.7)

[Infographic] Android Process - Importance Hierarchy

Today I was reading about Processes and Threads in Android. Well this is not my first time reading this document this time is just a review, repeat and reprogram my brain ...

Anyway I got an idea, I think it should be better if I have an image that can shows me all concept of this topic instead of reading whole document again.

Then I create this infographic after I've read about "importance hierarchy" in Android Process

here is what I've done