wood burning stoves 2.0*
The moose likes Java in General and the fly likes Possible to dynamically set CLASSPATH? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Possible to dynamically set CLASSPATH?" Watch "Possible to dynamically set CLASSPATH?" New topic
Author

Possible to dynamically set CLASSPATH?

Matt Senecal
Ranch Hand

Joined: Dec 01, 2000
Posts: 255
I have written a program that runs other Java applications. It uses ClassLoader as everything has to run on the same JRE, i.e., I cannot use Runtime.exec(). One of the problems I'm having is that each app requires a different CLASSPATH. Rather than set the system CLASSPATH to what may be a horrifically large value, I'd like to be able to set the CLASSPATH at runtime.
Is it possible to do this?


There's nothing more dangerous than a resourceful idiot. ---Dilbert
Mark Savory
Ranch Hand

Joined: Feb 08, 2001
Posts: 122
Hi Matt,
When the JRE starts, it loads the java classes that are in the classpath at startup. For that reason, you have to load all the classes that are required by the launchable application - not just the one with the main method. However, I don't know exactly what's the best way of doing this. Anybody else know?
Roseanne Zhang
Ranch Hand

Joined: Nov 14, 2000
Posts: 1953
Tomcat does exactly what you want. Look at server.xml in tomcat/conf directory.
I do not know the details, however, don't forget tomcat is opensource. When you need it, look into it, and share your experiences with us.
Thanks!
Roseanne
Join our SCJD Study Group when certified
ryan burgdorfer
Ranch Hand

Joined: Jan 24, 2001
Posts: 219
You can tell the VM a classpath to use for that session with the -cp switch...
Type java by itself at the cmd prompt for details.


<UL TYPE=SQUARE><I><LI>Ryan Burgdorfer<BR><LI>Java Acolyte</I></UL>
Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
If you want to make your application operating system specific, you can create separate .bat files for each use, and in the .bat files reset the classpath to what you want on the fly. But you would have to use Runtime.exec() to start the .bat files before loading up the applications.


"JavaRanch, where the deer and the Certified play" - David O'Meara
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Contrary to Mark's statement, the JVM doesn't load all classes at startup. It waits until they are needed. So yes, you can load classes dynamically, but there doesn't seem to be a good way to specify classpath dynamically. But another possibility is that you can move the class (or jar) files themselves to be in the classpath. Locate the file you need, copy/move/rename it to be in a directory which is in the classpath, and run Class.forName() to load it. Moving or renaming (using File.rename(), or Runtime.exec() to unix mv or windows rename commands) are probably quicker since you're not physically moving all the bytes in the file, only telling the system to rearrange some of the directory files. However you will probably want to be sure to move the file back to its original location immediately afterwards. If you're on a unix platform you could also use Runtime.exec() to set up a link to the file from the desired location. Good luck.
Of course, you'll probably learn a lot more if you follow Rosanne's suggestion and dig into the Tomcat code. Who knows, maybe they did what I suggest - but probably they found something much more elegant.


"I'm not back." - Bill Harding, Twister
Mark Savory
Ranch Hand

Joined: Feb 08, 2001
Posts: 122
Contrary to Jim's statement, the JVM does load all classes in the classpath at start-up. To verify this, run java with the '-verbose' parameter. This is why you must use something like ClassLoader to load classes that were not in the classpath at start-up. Adding classes to the classpath directories after the JVM is started does not make them available to your program. You must programatically load them.
Matt Senecal
Ranch Hand

Joined: Dec 01, 2000
Posts: 255
Thanks for all the good info, everyone!
Is there a way to explicitly tell ClassLoader where to find a class to load?
For example, I'm using it to load some classes that are already in the CLASSPATH:

But if they're not in the CLASSPATH, but I know where they are on disk, can I point ClassLoader to them?
---Matt
Originally posted by Mark Savory:
Contrary to Jim's statement, the JVM does load all classes in the classpath at start-up. To verify this, run java with the '-verbose' parameter. This is why you must use something like ClassLoader to load classes that were not in the classpath at start-up. Adding classes to the classpath directories after the JVM is started does not make them available to your program. You must programatically load them.


[This message has been edited by Matt Senecal (edited March 12, 2001).]
Mark Savory
Ranch Hand

Joined: Feb 08, 2001
Posts: 122
Matt,
I believe that the class java.net.URLClassLoader is what you can use. In spite of its name, it apparently can also be used to load classes from the local file system.
Matt Senecal
Ranch Hand

Joined: Dec 01, 2000
Posts: 255
Cool! Thanks!
Originally posted by Mark Savory:
Matt,
I believe that the class java.net.URLClassLoader is what you can use. In spite of its name, it apparently can also be used to load classes from the local file system.

Cindy Glass
"The Hood"
Sheriff

Joined: Sep 29, 2000
Posts: 8521
Understanding class loaders:
http://java.sun.com/docs/books/tutorial/ext/basics/load.html
Dynamic class loading:
http://java.sun.com/products//jdk/1.2/docs/guide/security/spec/security-spec.doc5.html
An example:
http://java.sun.com/sfaq/example/newLoader.java
A quote from the JVM Specifications shows that only on active use of a class is it loaded.

2.16.1 Virtual Machine Start-up
A Java Virtual Machine starts execution by invoking the method main of some specified class, passing it a single argument, which is an array of strings. This causes
the specified class to be loaded (�2.16.2), linked (�2.16.3) to other types that it uses, and initialized (�2.16.4). The method main must be declared public,
static, and void.
The manner in which the initial class is specified to the Java Virtual Machine is beyond the scope of this specification, but it is typical, in host environments that use
command lines, for the fully qualified name of the class to be specified as a command-line argument and for subsequent command-line arguments to be used as strings
to be provided as the argument to the method main. For example, in Sun's JDK implementation on UNIX, the command line
java Terminator Hasta la vista Baby!
will start a Java Virtual Machine by invoking the method main of class Terminator (a class in an unnamed package), passing it an array containing the four strings
"Hasta", "la", "vista", and "Baby!".
We now outline the steps the virtual machine may take to execute Terminator, as an example of the loading, linking, and initialization processes that are described
further in later sections.
The initial attempt to execute the method main of class Terminator discovers that the class Terminator is not loaded-that is, the virtual machine does not currently
contain a binary representation for this class. The virtual machine then uses a ClassLoader (�2.16.2) to attempt to find such a binary representation. If this process
fails, an error is thrown. This loading process is described further in (�2.16.2).
After Terminator is loaded, it must be initialized before main can be invoked, and a type (class or interface) must always be linked before it is initialized. Linking
involves verification, preparation, and (optionally) resolution. Linking is described further in �2.16.3.
Verification checks that the loaded representation of Terminator is well formed, with a proper symbol table. Verification also checks that the code that implements
Terminator obeys the semantic requirements of the Java Virtual Machine. If a problem is detected during verification, an error is thrown. Verification is described
further in �2.16.3.
Preparation involves allocation of static storage and any data structures that are used internally by the virtual machine, such as method tables. If a problem is detected
during preparation, an error is thrown. Preparation is described further in �2.16.3.
Resolution is the process of checking symbolic references from Terminator to other classes and interfaces, by loading the other classes and interfaces that are
mentioned and checking that the references are correct.
The resolution step is optional at the time of initial linkage. An implementation may resolve a symbolic reference from a class or interface that is being linked very
early, even to the point of resolving all symbolic references from the classes and interfaces that are further referenced, recursively. (This resolution may result in errors
from further loading and linking steps.) This implementation choice represents one extreme and is similar to the kind of static linkage that has been done for many
years in simple implementations of the C language.
An implementation may instead choose to resolve a symbolic reference only when it is actively used; consistent use of this strategy for all symbolic references would
represent the "laziest" form of resolution. In this case, if Terminator had several symbolic references to another class, the references might be resolved one at a
time-perhaps not at all, if these references were never used during execution of the program.
The only requirement on when resolution is performed is that any errors detected during resolution must be thrown at a point in the program where some action is
taken by the program that might, directly or indirectly, require linkage to the class or interface involved in the error. In the "static" example implementation choice
described earlier, loading and linking errors could occur before the program is executed if they involved a class or interface mentioned in the class Terminator or
any of the further, recursively referenced classes and interfaces. In a system that implemented the "laziest" resolution, these errors would be thrown only when a
symbolic reference is actively used.
The resolution process is described further in �2.16.3.
In our running example, the virtual machine is still trying to execute the method main of class Terminator. This is an attempted active use (�2.16.4) of the class,
which is permitted only if the class has been initialized.
Initialization consists of execution of any class variable initializers and static initializers of the class Terminator, in textual order. But before Terminator can be
initialized, its direct superclass must be initialized, as well as the direct superclass of its direct superclass, and so on, recursively. In the simplest case, Terminator
has Object as its implicit direct superclass; if class Object has not yet been initialized, then it must be initialized before Terminator is initialized.
If class Terminator has another class Super as its superclass, then Super must be initialized before Terminator. This requires loading, verifying, and preparing
Super, if this has not already been done, and, depending on the implementation, may also involve resolving the symbolic references from Super and so on,
recursively.
Initialization may thus cause loading, linking, and initialization errors, including such errors involving other types.
The initialization process is described further in �2.16.4.
Finally, after completion of the initialization for class Terminator (during which other consequential loading, linking, and initializing may have occurred), the method
main of Terminator is invoked.


[This message has been edited by Cindy Glass (edited March 12, 2001).]
Carl Trusiak
Sheriff

Joined: Jun 13, 2000
Posts: 3340
Originally posted by Mark Savory:
Contrary to Jim's statement, the JVM does load all classes in the classpath at start-up. To verify this, run java with the '-verbose' parameter.

I have to agree with Jim, and your use of vebose simply reinforces this. Yes, the JVM needs a lot of classes to support itself above your application like JarVerifier, StringTokenizer etc. however, I used your example to load a simple server application that I run and the 225 classes that were loaded, were all needed by the JVM or my application. This is well short of the 5,000+ classes that are in rt.jar itself not to mention i18n.jar, tools.jar, JavaMail API, j2ee.jar etc. all of which are in my classpath.

[This message has been edited by Carl Trusiak (edited March 12, 2001).]


I Hope This Helps
Carl Trusiak, SCJP2, SCWCD
Mark Savory
Ranch Hand

Joined: Feb 08, 2001
Posts: 122
I stand corrected. The JVM does not load all classes that are in the classpath at start-up. Thanks Carl & Jim for straighting me out on this one.
Matt Senecal
Ranch Hand

Joined: Dec 01, 2000
Posts: 255
Thanks, everyone! I got it working using a URLClassLoader.
Roseanne Zhang
Ranch Hand

Joined: Nov 14, 2000
Posts: 1953
!!!URLClassLoader Danger!!!
~~~~~~~~~~~~~~~~~~~
What you did will work until there is something called static You will be totally surprised by the behaviour of it. I'm not not kidding at all!!!
You can use them as long as you're aware of the problems. However, you are better off if you don't.
Be very very careful for this practice. Please read Ted Neward's excellent article on this topic:
Java statics
When is a static not a static?

Thanks!
Roseanne
Join our SCJD Study Group when certified
[This message has been edited by Roseanne Zhang (edited March 12, 2001).]
Matt Senecal
Ranch Hand

Joined: Dec 01, 2000
Posts: 255
Whoa! What makes you think I did it the way the whitepaper did it?
Originally posted by Roseanne Zhang:
[b]!!!URLClassLoader Danger!!!
~~~~~~~~~~~~~~~~~~~
What you did will work until there is something called static You will be totally surprised by the behaviour of it. I'm not not kidding at all!!!
You can use them as long as you're aware of the problems. However, you are better off if you don't.
Be very very careful for this practice. Please read Ted Newman's excellent article on this topic:
Java statics
When is a static not a static?

Thanks!
Roseanne
Join our SCJD Study Group when certified
[This message has been edited by Roseanne Zhang (edited March 12, 2001).][/B]

Roseanne Zhang
Ranch Hand

Joined: Nov 14, 2000
Posts: 1953
I didn't and don't know anything about how you are using it. But I think you'd better aware of it.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Possible to dynamically set CLASSPATH?