how to prevent a jar executed only once in a machine

J

John_Woo

Hi,

If my.jar is a swing UI app (or just a simple app), I'm wondering if
it's possible or how, that
this my.jar can be executed only once (no multi-session) in same
machine <or in same folder>?

Can any one tell?
 
S

Steve W. Jackson

John_Woo said:
Hi,

If my.jar is a swing UI app (or just a simple app), I'm wondering if
it's possible or how, that
this my.jar can be executed only once (no multi-session) in same
machine <or in same folder>?

Can any one tell?

There are a couple of common tricks used for preventing multiple
instances of an app from running.

One is to have your app open a ServerSocket on a specific port, which
prevents any other application on the same network interface from doing
the same (it'll already be in use when the second attempt occurs). But
this isn't always a good technique, depending on the port and other
factors.

Another is to create a file opened for output (I use a FileOutputStream)
and then obtain an exclusive lock on it. When the app terminates, the
lock is freed. I close the FileOutputStream at normal termination set
the file to delete when the JVM exits. When a second instance launches,
it may already find the file (in the event of an abnormal termination),
but it can't get a lock if another instance is running. I only use this
technique for restricting an individual user, so that the file is in the
user's home directory, but it can be readily adapted for system-wide use.

= Steve =
 
J

John_Woo

Steve said:
There are a couple of common tricks used for preventing multiple
instances of an app from running.

One is to have your app open a ServerSocket on a specific port, which
prevents any other application on the same network interface from doing
the same (it'll already be in use when the second attempt occurs). But
this isn't always a good technique, depending on the port and other
factors.

Another is to create a file opened for output (I use a FileOutputStream)
and then obtain an exclusive lock on it. When the app terminates, the
lock is freed. I close the FileOutputStream at normal termination set
the file to delete when the JVM exits. When a second instance launches,
it may already find the file (in the event of an abnormal termination),
but it can't get a lock if another instance is running. I only use this
technique for restricting an individual user, so that the file is in the
user's home directory, but it can be readily adapted for system-wide use.

= Steve =

Thanks lots Steve.
Let's talk about the second aproach further.

I know using:

f = new File("new file");
f.close();

to create a phycical file. but questions :

1. how to obtain an exclusive lock on it? from file API, I can only
see

setReadOnly()

2. if this app is terminated by unexpected way <like in unix, kill
-pid>, how to rm this file?
 
D

dsjoblom

John_Woo said:
Hi,

If my.jar is a swing UI app (or just a simple app), I'm wondering if
it's possible or how, that
this my.jar can be executed only once (no multi-session) in same
machine <or in same folder>?

Can any one tell?

In addition to the more traditional advice, if you happen to be
deploying your app with java webstart, you can achieve this
functionality easily. See
http://java.sun.com/j2se/1.5.0/docs/guide/javaws/jnlp/ and look up
SingeInstanceListener and SingleInstanceService.

Regards,
Daniel Sjöblom
 
J

John_Woo

In addition to the more traditional advice, if you happen to be
deploying your app with java webstart, you can achieve this
functionality easily. See
http://java.sun.com/j2se/1.5.0/docs/guide/javaws/jnlp/ and look up
SingeInstanceListener and SingleInstanceService.

Regards,
Daniel Sjöblom

Thanks for the info, Daniel.

It seemed that's good to prevent multiply login.
My case is to allow same user login twice or more, but in different
machine or different folder, b/c it's swing UI app, they are allowed to
copy the my.jar anywhere except we are to prevent them execute same
my.jar twice or more.

John
 
S

Steve W. Jackson

John_Woo said:
Thanks lots Steve.
Let's talk about the second aproach further.

I know using:

f = new File("new file");
f.close();

to create a phycical file. but questions :

1. how to obtain an exclusive lock on it? from file API, I can only
see

setReadOnly()

2. if this app is terminated by unexpected way <like in unix, kill
-pid>, how to rm this file?

I do something like this:

File homeDir = new File(System.getProperty("user.home"));
File f = new File(homeDir, "lockFileName");
f.createNewFile();

That creates the file, if it's not present, in the user's home
directory. But it doesn't care if the file's already present. (I'm
omitting try/catch blocks for brevity.)

Then I create a java.io.FileOutputStream around that file:

FileOutputStream fos = new FileOutputStream(f);

The file locking mechanism I use was added in Java 1.4. It's a
java.nio.channels.FileLock. You obtain one like this:

FileLock lock = fos.getChannel().tryLock();

If that succeeds, you've got a non-null FileLock object and an exclusive
lock on the output file. For good measure, I write a single byte to the
file. And I have to keep the FileOutputStream reference as long as my
application is running.

To get the JVM to delete the file automatically, I call:

f.deleteOnExit();

When my app is ready to terminate normally, I close the FileOutputStream
reference I've kept. If I don't, then the deleteOnExit() call has no
effect. If I do close it, then that file goes away automagically.

If your app terminates abnormally -- or you forget to close the output
stream -- then the file will already be there next time around, but that
wouldn't break this approach. The lock attempt will work fine again.
However, if a second instance of your app runs it'll be able to get the
file, but the tryLock() call will result in a null FileLock object when
it cannot lock the file. So the response would be to inform the user
that multiple instances aren't allowed and force a JVM shutdown.

= Steve =
 
J

John_Woo

Steve said:
I do something like this:

File homeDir = new File(System.getProperty("user.home"));
File f = new File(homeDir, "lockFileName");
f.createNewFile();

That creates the file, if it's not present, in the user's home
directory. But it doesn't care if the file's already present. (I'm
omitting try/catch blocks for brevity.)

Then I create a java.io.FileOutputStream around that file:

FileOutputStream fos = new FileOutputStream(f);

The file locking mechanism I use was added in Java 1.4. It's a
java.nio.channels.FileLock. You obtain one like this:

FileLock lock = fos.getChannel().tryLock();

If that succeeds, you've got a non-null FileLock object and an exclusive
lock on the output file. For good measure, I write a single byte to the
file. And I have to keep the FileOutputStream reference as long as my
application is running.

To get the JVM to delete the file automatically, I call:

f.deleteOnExit();

When my app is ready to terminate normally, I close the FileOutputStream
reference I've kept. If I don't, then the deleteOnExit() call has no
effect. If I do close it, then that file goes away automagically.

If your app terminates abnormally -- or you forget to close the output
stream -- then the file will already be there next time around, but that
wouldn't break this approach. The lock attempt will work fine again.
However, if a second instance of your app runs it'll be able to get the
file, but the tryLock() call will result in a null FileLock object when
it cannot lock the file. So the response would be to inform the user
that multiple instances aren't allowed and force a JVM shutdown.

= Steve =

Hi, Steve
It's appreciated what suggested.

1 more question:
if the created file is still, and permission changed to Readonly, then
no way to lock it.
so,
1. how to set to write in my app?
2. if I want to update timestamp to a file which is already existed in
my.jar, can u tell how to write this file <not outside my.jar>?
 
S

Steve W. Jackson

[ snip ]
Hi, Steve
It's appreciated what suggested.

1 more question:
if the created file is still, and permission changed to Readonly, then
no way to lock it.
so,
1. how to set to write in my app?
2. if I want to update timestamp to a file which is already existed in
my.jar, can u tell how to write this file <not outside my.jar>?

I'm not quite sure I understand the question.

If the objective is to prevent the same user from running the program,
you shouldn't want to use a read-only file. Simply create a new file
with a name unique to your application, open it for output, and get an
exclusive lock. Any failure to get the lock means it's locked by
another instance of your application.

I suppose you could use an existing file, opened with a FileInputStream
in a fashion similar to what I described. The FileInputStream class has
the getChannel() method to return a FileChannel, and it's that class
which provides the tryLock() method used to get an exclusive lock on the
file.

Writing to a file inside your own jar file is another matter altogether
and not something to be undertaken lightly. Manipulating jar file
contents is complex enough. But doing so when your application is
running from the jar is something else entirely -- and I wouldn't have
the first idea whether it's really even possible.

= Steve =
 
R

Red Orchid

Message-ID: said:
If your app terminates abnormally -- or you forget to close the output
stream -- then the file will already be there next time around, but that
wouldn't break this approach. The lock attempt will work fine again.
However, if a second instance of your app runs it'll be able to get the
file, but the tryLock() call will result in a null FileLock object when
it cannot lock the file. So the response would be to inform the user
that multiple instances aren't allowed and force a JVM shutdown.

In addition to the above ...

Though an user terminates a program, some bugs of her
(including third party libraries) may give rise to a state that
she is running abnormally. Then, the file's lock will not
be released.

Therefore, I think that it is needed to check whether she is
running abnormally or not.

For example, (Assuming that the 'PRA' is GUI program)

1) When an user executes a close menu, PRA writes
"PRA_USR_CLOSED == true" key to a registry of OS.

2) A second instance of the program checks the followings.

If (the file is in a lock state) {
If (PRA_USR_CLOSED == true) {
// process the abnormal state.
}
else {
// inform the user ...
}
}
 
A

Andrew T.

John_Woo said:
....
It seemed that's good to prevent multiply login.
My case is to allow same user login twice or more, but in different
machine or different folder, b/c it's swing UI app, they are allowed to
copy the my.jar anywhere except we are to prevent them execute same
my.jar twice or more.

I have shareware programs that allow you to run them
a number of times before they 'lock you out' and
demand a registration key.

Is *that* what you mean? You only want to allow the
end user to run your application a single time (before
something else happens - like a registration or payment).

[ If that is right, JWS might also be able to help with that. ]

Andrew T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,828
Latest member
LauraCastr

Latest Threads

Top