how to execute a class as an external Java application

M

Marcin Rodzik

Following my previous thread...
http://groups.google.com/group/comp...90646/70e33a7d6bb1181a?hl=en#70e33a7d6bb1181a

How can I execute another class existing in my project as a standalone
(external) Java application using the method Runtime.exec(String) ?
There is some problem with class visibility... I want it to be
resistant to user's possible actions such as moving a file to another
directory... I would like to enclose everything in one JAR file and
not to think about where the user will place it (such a solution was
suggested in: http://groups.google.com/group/comp..._frm/thread/11e367a28a0b41fd/9d69aa5ef2e34211
but no detailed description how to achieve it was given).

I tried to do it on my own:
proc = Runtime.getRuntime().exec("java ClassName");

JVM is lanuched and finishes because it can't find the class. Or more
precisely, JVM can see the class only if it is located in working
directory and everything is default ("no") package. What if want to
invoke a class from another package?
 
M

markspace

Marcin said:
I tried to do it on my own:
proc = Runtime.getRuntime().exec("java ClassName");

JVM is lanuched and finishes because it can't find the class. Or more

The easy way around this is to add the following to the manual:

"Set the CLASSPATH correctly to include any external Java classes to be
executed."
precisely, JVM can see the class only if it is located in working
directory and everything is default ("no") package. What if want to
invoke a class from another package?

Add the fully qualified name to the class when you execute it.

This is very basic stuff. Take a look at the first lesson in this free
online course (skip the IDE stuff, go right to Exercise 2 in the
homework section, "Write, compile and run... using the command line tool":

http://www.javapassion.com/javaintro/

Then check out the online pages from Sun where they describe the command
line tools.
 
A

Arne Vajhøj

Marcin said:
Following my previous thread...
http://groups.google.com/group/comp...90646/70e33a7d6bb1181a?hl=en#70e33a7d6bb1181a

How can I execute another class existing in my project as a standalone
(external) Java application using the method Runtime.exec(String) ?
There is some problem with class visibility... I want it to be
resistant to user's possible actions such as moving a file to another
directory... I would like to enclose everything in one JAR file and
not to think about where the user will place it (such a solution was
suggested in: http://groups.google.com/group/comp..._frm/thread/11e367a28a0b41fd/9d69aa5ef2e34211
but no detailed description how to achieve it was given).

I tried to do it on my own:
proc = Runtime.getRuntime().exec("java ClassName");

JVM is lanuched and finishes because it can't find the class. Or more
precisely, JVM can see the class only if it is located in working
directory and everything is default ("no") package. What if want to
invoke a class from another package?

You can find out where your code are from inside your code
quite easily and set classpath appropriately.

But does the other class have a main method ?

Arne
 
M

Marcin Rodzik

You can find out where your code are from inside your code
quite easily and set classpath appropriately.
And what if I pack all classess to a JAR and a user execute JAR from
another directory, not from the one the JAR is located in?
How can I set the classpath "appropriately" if I don't know the
directory the user will put my classes in?
But does the other class have a main method ?
Yes, of course.

MR
 
A

Arne Vajhøj

Marcin said:
And what if I pack all classess to a JAR and a user execute JAR from
another directory, not from the one the JAR is located in?
How can I set the classpath "appropriately" if I don't know the
directory the user will put my classes in?

As I said you ask Java where your code are located.

I have used this code for many years:

private static String getPath(Class cls) {
String cn = cls.getName();
String rn = cn.replace('.', '/') + ".class";
String path =
GetPath.class.getClassLoader().getResource(rn).getPath();
int ix = path.indexOf("!");
if(ix >= 0) {
path = path.substring(0, ix);
}
return (new File(path)).getParent();
}

but there are even easier ways of doing it.

Arne
 
M

Marcin Rodzik

Thank you for your help, now it seems to me that I managed to reduce
the problem to one specific issue with JAR files.

Before I used IDE which places all the classes into a build/classes
subdirectiories (reflecting the package structure). So I added a JVM
argument "-cp build/classes", and now it works from IDE :) no matter
if I specify class to be invoked with packagename/ClassName or
packagename.ClassName (dots are traslated into slashes). The only
condition which has to be fulfilled is that there must exist directory
packageName with a file ClassName.class in the working directory or
the directory pointed with -cp switch. And is OK. It was not so
difficult to find out, but I got that only after I read John's
example.

Now, how to do it if I pack my program into a JAR? When I launch JAR,
the package with the class I need are not in the working directory but
in the JAR... I believe Arne's code can deal with this issue, anyway I
have not yet succeeded... I'll be working further.

MR
 
M

Marcin Rodzik

Btw. have you got any idea why my NetBeans started to generate a wrong
manifest in the jar? It contains no main class specification, I have
to add it manually which is pretty annoying!

MR
 
M

Marcin Rodzik

Arne,
your code helps me a lot, however, in my opinion it doesn't work,
moreover, it won't compile :) I think you just wrote it without
checking it.

The first, you meant probably:
String path = cls.getClassLoader().getResource(rn).getPath();

The second, I don't have the faintest idea why are you serching for
"!", maybe you intended to search for "/" ?

Another problem is that the function returns the path to the directory
containing the class file, which is wrong, in my opinion, if a class
is a part of a package. In that case, I think, it's necessary to
invoke this class with a "fully qualified name" and the appropriate
directory specified. And the appropriate directory in this case is the
one containing the package directory, not the class file.

But, of cource, I can be wrong.

MR
 
M

Marcin Rodzik

Arne (and All),
I have written my own version of the method... it's pretty much more
complicated than yours but it seems to me that everything was needed
in order to make it work!

private static Process startClass(Class cls) {
String resource = cls.getName().replace(".", "/") + ".class";
String path = cls.getClassLoader().getResource
(resource).getPath();
Process process = null;

int ix = path.lastIndexOf(resource);
while (ix >= 0) {
path = path.substring(0, ix);
if (path.endsWith("!"))
ix = path.lastIndexOf("!");
else if (path.endsWith("/"))
ix = path.lastIndexOf("/");
else
ix = -1;
}
if (path.startsWith("file:/"))
path = path.substring(6);
try {
process = Runtime.getRuntime().exec("java "
+ ((path.compareTo("") == 0) ? "" : ("-cp " + path + "
"))
+ cls.getName());
}
catch (IOException ex) {
ex.printStackTrace();
process = null;
}
return process;
}
 
L

Lew

Marcin said:
Thank you for your help, now it seems to me that I managed to reduce
the problem to one specific issue with JAR files.

Before I used IDE which places all the classes into a build/classes
subdirectiories (reflecting the package structure). So I added a JVM
argument "-cp build/classes", and now it works from IDE :) no matter
if I specify class to be invoked with packagename/ClassName or
packagename.ClassName (dots are traslated into slashes). The only
condition which has to be fulfilled is that there must exist directory
packageName with a file ClassName.class in the working directory or
the directory pointed with -cp switch. And is OK. It was not so
difficult to find out, but I got that only after I read John's
example.

Now, how to do it if I pack my program into a JAR? When I launch JAR,
the package with the class I need are not in the working directory but
in the JAR... I believe Arne's code can deal with this issue, anyway I
have not yet succeeded... I'll be working further.

You specify the JARs that belong in the class path in the "Class-Path" element
of the JAR manifest. Typically that means deploying the dependency JARs in a
subdirectory (possibly ./ ) of the one that holds the application JAR.
Running a Java class with "java -jar", Java ignores the CLASSPATH environment
variable (envar) and "-classpath" command-line option, taking its class path
entirely from the JAR manifest.

Others have linked you to docs.
 
D

Donkey Hottie

Marcin Rodzik said:
if (path.startsWith("file:/"))
path = path.substring(6);

I may have a big misundestanding, but I thin the URL prefix is file:// and
if a file on root file system is referred the path should start with
file:///.

I would be tempted to write

if (path.startsWith("file://"))
path = path.substring(7);

Please tell me if I'm wrong.
 
R

Roedy Green

How can I execute another class existing in my project as a standalone
(external) Java application using the method Runtime.exec(String) ?

this is an odd thing to do. You can do it very easily in the same JVM
with SomeClass.main ( args );

Then it will run in the same JVM, and has access to all the classes
already loaded.

If you fire up a new JVM, you will have quite a delay and quite a RAM
penalty.

Why would you want to?

Assuming you have a good reason:

see http://mindprod.com/jgloss/exec.html

just use java.exe as the name of your executable and the name of your
class as the parameter. Make sure java.exe is on the path, or use a
fully qualified name.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Let us pray it is not so, or if it is, that it will not become widely known."
~ Wife of the Bishop of Exeter on hearing of Darwin's theory of the common descent of humans and apes.
 
R

Roedy Green

I'm sorry, it doesn't satisfy me :/

You mean stuff like this: java.packagename.ClassName ?

What you need to know is the same you would need to know to start up
java.exe on any class, without using exec.

See http://mindprod.com/jgloss/javaexe.html
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Let us pray it is not so, or if it is, that it will not become widely known."
~ Wife of the Bishop of Exeter on hearing of Darwin's theory of the common descent of humans and apes.
 
M

Marcin Rodzik

I may have a big misundestanding, but I thin the URL prefix is file:// and
if a file on root file system is referred the path should start with
file:///.

I've checked what is in my URL I'm receiving using the code as above
and it starts just with "file:/". Maybe it is an error in the
implementation of JVM for Windows?
If the file is on root file system a '/' sign is added, however, it is
not added before "file:"... Or maybe I'm receiving just "file:" prefix
followed by the aforementioned '/' sign indicating the absolute
filepath? (as if "//" were not used at all).

I believe the code I produced is a little *too* complicated, but I was
adding different lines until it started working... (maybe I've added
too much or simply I went a wrong way).
 
A

Arne Vajhøj

Marcin said:
your code helps me a lot, however, in my opinion it doesn't work,
moreover, it won't compile :) I think you just wrote it without
checking it.

The first, you meant probably:
String path = cls.getClassLoader().getResource(rn).getPath();

It was tested, but:

String path = GetPath.class.getClassLoader().getResource(rn).getPath();

assumed the code was in a class GetPath.
The second, I don't have the faintest idea why are you serching for
"!", maybe you intended to search for "/" ?

Because classes in jar files are named:

jar URL!path to class
Another problem is that the function returns the path to the directory
containing the class file, which is wrong, in my opinion, if a class
is a part of a package. In that case, I think, it's necessary to
invoke this class with a "fully qualified name" and the appropriate
directory specified. And the appropriate directory in this case is the
one containing the package directory, not the class file.

For your usage you would need to convert the path to class
to the app classpath by stripping of the package path.

Arne
 

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,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top