Wednesday, July 23, 2008

Single Instance From Your Application ?

Introduction:

some people want to have only single instance running from their application and if the user clicked/started the executable file for the application again nothing will happen or the user will be prompted that there is an already running instnace(something like MSN you only have one instance an no matter how many time you click the MSN exe icon you will just get the same instance).


Chit Chat at a cafe':

one day four programmers were having a coffee break and one of them was having a bad day trying to make a single instance from his application

programmer 1: uffff i cant enjoy my java coffee :(

programmer 2: oh why is that ?

programmer 1: i want the user only to have one instance from my application and no matter how many time he run the application he will just get one instance.

porgrammer 2:oh come on it is not that hard i have done something like that and here is what i have done :why don’t we use file a config. for example and set value in the file to indicate that there is already running instance or even create a file named for example blabla.lock and by this way i can know that the application has an instance running already and when the application is done just change the value or delete the lock file to indicate that it is done and no instance is running.

programmer 3: opps hey programmer 2 i think you have a problem in your approach

programmer 1: oh really ! what is it ?

programmer 3 : well what if the machine crashed ?you will still have the value that indicates that there is an instance running from your application.

programmer 1 : mmm you are right , i was thinking to improve my solution by using registry entries :( ohh and how can we solve such thing programmer 3?

programmer 3: well you can use sockets for that ! how is that ? let me tell you ,just connect to a port and try to listen on this port and when you click on the application icon again to start up new instance it will just go and try to listen on the same port it will get exception (as there should be only one application listening ) .

programmer 1 , 2 : ohhh :O wow nice one

programmer 3: now we can enjoy our coffee :D

programmer 4: (shaking his head) well cant we just make a better solution ???


Make a room for Programmer 4:

programmer 1,2,3 : huh what do you mean ?

programmer 4: well didnt you hear semaphore thing ?

programmer 1,2,3: huh yea but what does it have to do with our case ?

programmer 4 : well it can solve your problem but i will you another way to do so

programmer 4: Semaphore this is the magic word , in old days C++ developers used to do so (use semaphore in order to make only one instance from you application) so when you start my application there will be lock acquired and when i try to start another instancei will check for this lock if it is not acquired so this mean that i am the first instance else am not and i should throw exception or so.

programmer 1,2,3 :oh so how will we handle this issue then we didnt get the solution and our coffee is getting cold :( ?

programmer 4: (while drinking his coffee) well we can achieve the desired functionality through locking mechanism from files introduced in java.nio package.

programmer 1,2,3 : ok tell us how can we do this

programmer 4: we will acquire a lock on the file (lets say our main class file) and when our main starts it will try to acquire lock on this file. if it succeeds this mean that it is the first instance of our program and if it fails (due to already exist lock ) this mean that it is not the first instance of our application note that we will release the lock once we end the application and there wont be any hurm if the application crashed or so as we can re-start it and it will work just fine.

programmer 4: ok does any one have a paper and a pen ?

programmer 1,2,3: (the three in the same voice) sure here you are

programmer 4: ok let me write the code for you

RandomAccessFile randomFile=new RandomAccessFile("C:/myMainClass.class","rw");
FileChannel channel=randomFile.getChannel();
if(channel.tryLock()==null) //we couldnt acquire lock as it is already locked by another program instance)
System.out.println("Sorry but you have an already running instnace from the application");

programmer 4: here you are

programmer 1,2,3 : WOOOW we didnt know that, this looks like a magic

programmer 1: yepiiii hey seems that i will leave early today from my work :D , although the coffee is cold now but i still enjoy it ;)

12 comments:

Anonymous said...

Good for people to know.

panschk said...

Good post - Helpful Tip plus some entertainment value. That's great;-)

I used that approach in my project and it works like a charm.

Ahmed Ali said...

panschk,

Thanks for your comment :) am glad you found it helpful and enjoyed it.

Thanks,

jdv145 said...

Well nice tip, and this is exactly what i did with my java program. The problem is that the program (needs to) run as admin and then the trylock thing doesn't work.If you are root on linux you will get the lock immediately, even if it is already locked (at least that is whats happening on my ubuntu box). So sockets are still a better solution in some cases.

Ahmed Ali said...

jdv145,

Thanks for you comment and hint, I tried it on windows with any credential and worked fine as for Linux unfortunately I didn’t test it on but as you can see the socket solution have some drawbacks but as you said in some cases (as you said if you are not the root) this might work for you

Thanks,

Viktor VAD said...

Just a reminder for the author:

Please correct the package name to "java.io" from java.nio as it is a bit confusing for the newbee-s like me :)

Other from that, you are my personal jesus christ! ^_^

Ahmed Ali said...

Ikon,

Thanks for your very nice comment :D

you will have to import the nio-which is not the same package as java.io- which stands for New IO as we are using FileChannel which resides in this package

Thanks agin for your comment :)

Viktor VAD said...

Oh noew I see, thank you, you are right, I missed the nio package. Yes FileChannel is in that one. I'm sorry for not thinking over! :)

Ahmed Ali said...

Ikon,

no problem at all ,anytime my man :)

Anonymous said...

A FLAW!!
what if i copy the application to some other directory and run it? in this case, the application can be run easily. rather use a “UNIQUE” location for the “.lock” file or implement the whole mechanism using sockets.
use some port “xyz” on the system to check the mechanism.

Ahmed Ali said...

Hello,

Thanks for your comment but actually it is not a flaw :) in my example i was just trying to obtain lock on a class file (just simple example i gave so reader can understand) in real life this wont work for sure and you will need something like lock file as you said and most of the wep application servers do so (for example WebLogic)

and one more thing about lock file ,if you shutdown the application in a wrong manner (kill it) the lock file will stil exist so you will need to handle this case also :)

Thanks for your comment :)

Ahmed Ali said...

Hello,

Thanks a lot for your nice comment, glad you liked it and found it useful

Thanks,
Ahmed Ali