participate


Java Runtime Environment (JRE) - Modify Classpath At Runtime [Locked]
This topic is locked
<<   Back to Forum  |   Give us Feedback
This topic has 59 replies on 4 pages.    1 | 2 | 3 | 4 | Next »
antony_miguel
Posts:14
Registered: 4/20/00
Modify Classpath At Runtime   
Sep 17, 2002 4:02 AM

 
I've seen a lot of forum posts about how to modify the classpath at runtime and a lot of answers saying it can't be done. I needed to add JDBC driver JARs at runtime so I figured out the following method.

The system classloader (ClassLoader.getSystemClassLoader()) is a subclass of URLClassLoader. It can therefore be casted into a URLClassLoader and used as one.

URLClassLoader has a protected method addURL(URL url), which you can use to add files, jars, web addresses - any valid URL in fact.

Since the method is protected you need to use reflection to invoke it.

Here's some code for a class which adds a File or URL to the classpath:


public class ClassPathHacker {
 
private static final Class[] parameters = new Class[]{URL.class};
 
public static void addFile(String s) throws IOException {
	File f = new File(s);
	addFile(f);
}//end method
 
public static void addFile(File f) throws IOException {
	addURL(f.toURL());
}//end method
 
 
public static void addURL(URL u) throws IOException {
		
	URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
	Class sysclass = URLClassLoader.class;
 
	try {
		Method method = sysclass.getDeclaredMethod("addURL",parameters);
		method.setAccessible(true);
		method.invoke(sysloader,new Object[]{ u });
	} catch (Throwable t) {
		t.printStackTrace();
		throw new IOException("Error, could not add URL to system classloader");
	}//end try catch
		
}//end method
 
}//end class
 
hanxue
Posts:101
Registered: 2/9/00
Re: Modify Classpath At Runtime   
Oct 13, 2002 7:40 PM (reply 1 of 59)  (In reply to original post )

 
I guess the files need to have the necessary import statements =)

Included below:

import java.lang.reflect.*;
import java.io.*;
import java.net.*;
 
epkmhag
Posts:1
Registered: 1/11/99
Re: Modify Classpath At Runtime   
Apr 4, 2003 1:36 AM (reply 2 of 59)  (In reply to #1 )

 
Thanks! Has been looking for a long time to accompish this, finally a good and easy solution!
 
javafan13
Posts:4
Registered: 4/5/03
Re: Modify Classpath At Runtime   
Apr 5, 2003 5:53 AM (reply 3 of 59)  (In reply to original post )

 
This should be added in standard docs, thanks for posting it!
 
i077380
Posts:1
Registered: 4/25/03
Re: Modify Classpath At Runtime   
Apr 25, 2003 4:20 AM (reply 4 of 59)  (In reply to original post )

 
Hi your the greatest! I'm looking for several days to dynamically modify my classpath. Tnx!
Regards, Tom.
 
LuethjeC
Posts:47
Registered: 8/8/99
Re: Modify Classpath At Runtime   
Jun 3, 2003 12:11 PM (reply 5 of 59)  (In reply to original post )

 
Hi,
I don't understand how I'm supposed to use this class. I mean, when I have a class 'dir_1.dir_2.MyClass' in the classpath 'c:\myclasspath\' what should I do to make an instance of myClass?

What an I doing wrong here:

String classpath = "c:\myclasspath\";
ClassPathHacker.addFile(classpath);
clazz = Class.forName("dir_1.dir_2.MyClass");

I get a java.lang.ClassNotFoundException.

Any help very much appreciated. Thanks!

Regards,
Claus
 
chrisrob123
Posts:4
Registered: 2/4/02
Re: Modify Classpath At Runtime   
Aug 9, 2003 7:56 AM (reply 6 of 59)  (In reply to original post )

 
Antony Miguel, your name should be up in lights on Broadway. Well at least I hope Sun made you an offer of employment.

When I first needed to dynamically add a jarfile to the classpath I checked the API for ClassLoader confidently expecting to find an addResource(URL) or setResource(URL) method. I couldn't believe it when I discovered there is no standard method of modifying the JRE's classpath.

Your ClassPathHacker is now a standard in our "foundation" classes.

Thanks, thanks, thanks.
 
shchuka
Posts:1
Registered: 3/18/98
Re: Modify Classpath At Runtime   
Aug 21, 2003 7:04 AM (reply 7 of 59)  (In reply to original post )

 
Antony Miguel, you are the genius! I spent two weeks fighting with multiple classloaders - and still couldn't get everything done the way I needed.

This is just amazing!

One reservation, though - are we guaranteed that the system classloader will stay a subclass of URLClassLoader in the future versions of Java on all platforms (well, at least, NT, Mac, Linux, and Solaris)?

Greatest thanks,
-Aleks
 
arajput
Posts:7
Registered: 2/19/01
Re: Modify Classpath At Runtime   
Sep 3, 2003 7:25 AM (reply 8 of 59)  (In reply to #7 )

 
Why not use new URLClassLoader directly and then do getResource() for any file needed at runtime from the newly added resource? This way you dont have to worry about future implementation of ClassLoader.getSystemClassLoader() to return URLClassLoader
Ashish
 
bladester
Posts:3
Registered: 8/25/03
Re: Modify Classpath At Runtime   
Oct 10, 2003 12:25 AM (reply 9 of 59)  (In reply to original post )

 
kudos..
 
ramat123
Posts:5
Registered: 5/4/00
Re: Modify Classpath At Runtime   
Dec 28, 2003 12:25 AM (reply 10 of 59)  (In reply to original post )

 
Antony Hi

I was very glad to read you solution to my problem.

Can you please give a few words about it. I am not sure I understand why did you use reflection.

Thank you so much,

David
 
buckman1
Posts:1,013
Registered: 3/12/02
Re: Modify Classpath At Runtime   
Dec 29, 2003 7:54 AM (reply 11 of 59)  (In reply to #10 )

 
I have to agree with arjput. Hacking and using reflection to make use of a protected method is not a very good thing to do. It works, yes, but the reflection API wasn't meant to hack into system classes such as the application classloader.

A better approach is to launch your app with your own classloader. I saw an article on this onetime, I think it's something like -Dbootstrap.classloader=your-classloader-class but I forget.

The approach I prefer is a launching app to create a custom loader (that extend URLClassLoader) and load all my classes from that point. One advantage to this is you can "reload" your application at runtime without having to stop/start the JVM and your app.

An even better approach is to develop with a plugin engine like mine at www.sourceforge.net/genpluginengine. It provides a "container" for plugins that can depend on one another, load/unload/reload, provide services, and so forth. The benefit is not only the container managed plugin lifecycle, but the easier development across teams, easier management of specific modules of an application, extensibility it adds to an applcation, and the development time it saves. Plugins are much smaller than the whole (usually) so take less time to build and with the (soon to be added) watch and reload system, modifying a plugin get's it reloaded at runtime so that you no longer have to restart your jvm and app, possibly log in, etc. IT reloads the plugin and any affected dependent plugins, as necessary at runtime.
 
antony_miguel
Posts:14
Registered: 4/20/00
Re: Modify Classpath At Runtime   
Jan 7, 2004 8:58 AM (reply 12 of 59)  (In reply to #10 )

 
Hi, glad to see my code has been of some use.

To clear a few things up:

There are lots of ways to load classes dynamically at runtime. The purpose of the code above is to be able to easily load classes at runtime as if they had been loaded as normal from the very beginning. This might sound odd but if you're using third party code which you don't have control over (e.g. JDBC drivers in my original example) then it can easily be a requirement.

If you don't have control over the command line or you don't want to make restrictions about command line usage you can't specify a proprietary classloader on the command line. If the (potentially third party) code you are loading does it's own complex dynamic class loading then it may expect to get it's classes and resources from the system classloader (e.g. any code that does ClassLoader.getSystemClassLoader() to get class references or resources etc).

The code above is not necessarily the best way for everyone to dynamically load their code - but using it guarantees the dynamically loaded code will work as it would if it had been loaded by the system classloader at the very beginning. This is particularly important if you're loading third party code which you can't fully test with some other dynamic loading method.

Hope this clears up why I used reflection and the system classloader etc rather than some other method. The point is not to load code dynamically in the nicest way, but to load it so as to be indistinguishable from loading it as normal.

Thanks

Antony
 
Eanna
Posts:7
Registered: 3/25/99
Re: Modify Classpath At Runtime   
Jul 28, 2004 6:00 AM (reply 13 of 59)  (In reply to original post )

 
Hey there Antony,

Fair play, you're a star!
I was getting there, had figured that the system class loader was a URLClassLoader, but you've made it clear and simple.
You've saved me from dumping that code, and trying yet another route.

I didn't know about Method:setAccessible(boolean). I've now got a handful of uses for this method, specifically with some Eclipse classes that I now realise that won't need to subclass any more.


Thanks buddy,

Irish ?anna
 
shankar.unni
Posts:749
Registered: 6/23/98
Re: Modify Classpath At Runtime   
Jul 28, 2004 1:29 PM (reply 14 of 59)  (In reply to original post )

 
The system classloader (ClassLoader.getSystemClassLoader()) is a subclass of
URLClassLoader.

Not always. For most applications, yes. So to be careful, you should do an "instanceof" check, and throw an exception (or log an error) if it's not.

method.setAccessible(true);

But ooh, this is a sneaky way around the API protections! Naturally, folks, don't always depend on this working, OK? It's much better to use the documented APIs to achieve this.
 
This topic has 59 replies on 4 pages.    1 | 2 | 3 | 4 | Next »
Back to Forum
 
Read the Developer Forums Code of Conduct

Click to email this message Email this Topic

Edit this Topic
  
 
 
Forums Statistics
    Users Online : 28
  • Guests : 133

About Sun forums
  • Oracle Forums is a large collection of user generated discussions. It is here to help you ask questions, find answers, and participate in discussions.

    Check out our guide on Getting started with Oracle Forums for a full walkthrough of how to best leverage the benefits of this community.

Powered by Jive Forums