September 17, 2009

runtime replacement of jar file

« Java XML-RPC - Example | Main | How to resolve an artifact with maven embedder »

First solution that comes to mind would be to use OSGI. Sometime you don't want to setup a whole OSGi environment to replace just one jar, or even just one file.

An alternative is to use a custom classloader.

 

  8 import java.net.URL; 
  9 import java.net.URLClassLoader; 
 10 import java.util.List; 
 11  
 12 /** 
 13  * own classloader, delegating not found classes to parent classloader. 
 14  ... 
 15  */ 
 16 public class DelegatingClassLoader extends URLClassLoader { 
 17  
 18     private ClassLoader mainLoader; 
 19     private List < URL > defaultUrls; 
 20 
 21     /** 
 22      * default contrsuctor. 
 23      * @see URLClassLoader#URLClassLoader(java.net.URL[]) 
 24      */ 
 25     public DelegatingClassLoader() { 
 26         super(new URL[0]); 
 27     } 
 28 
  29     /** 
 30      * getter for default url list. 
 31      * @return list of urls 
 32      */ 
 33     public List < URL > getDefaultUrls() {
  34         return this.defaultUrls; 
 35     } 
 36  
 37     /** 
 38      * setter for default url list. 
 39      * @param defaultUrlsToBeSet list of url 
 40      */ 
 41     public void setDefaultUrls(List < URL > defaultUrlsToBeSet) { 
 42         this.defaultUrls = defaultUrlsToBeSet; 
 43     } 
 44  
 45     /** 
 46      * adding url to classpath. 
 47      * @see URLClassLoader#addURL(java.net.URL) 
 48      * @param url to be added 
 49      */ 
 50     public void addUrl(URL url) { 
 51         addURL(url); 
 52     } 
 53  
 54     /** 
 55      * activate this classloader, remember parent loader. 
 56      */ 
 57     public void activate() { 
 58         // backup parent class loader 
 59         this.mainLoader = Thread.currentThread().getContextClassLoader(); 
 60          
 61         // add default urls 
 62         for (URL url : this.defaultUrls) { 
 63             addURL(url); 
 64         } 
 65  
 66         // set this class loader as default for thread 
 67         Thread.currentThread().setContextClassLoader(this); 
 68     } 
 69  
 70     /** 
 71      * restore parent classloader. 
 72      */ 
 73     public void restore() { 
 74         Thread.currentThread().setContextClassLoader(this.mainLoader); 
 75     } 
 76  
 77     /** 
 78      * {@inheritDoc} 
 79      */ 
 80     @Override 
 81     public Class loadClass(String name) throws ClassNotFoundException { 
 82         try { 
 83             return super.loadClass(name); 
 84         } catch (NoClassDefFoundError ncde) { 
 85             return this.mainLoader.loadClass(name); 
 86         } catch (ClassNotFoundException cnfe) { 
 87             return this.mainLoader.loadClass(name); 
 88         } catch (UnsupportedClassVersionError ucve) { 
 89             throw new RuntimeException("Bad class " + name, ucve); 
 90         } 
 91 
  92     } 
 93  
 94     /** 
 95      * {@inheritDoc} 
 96      */ 
 97     @Override 
 98     public URL getResource(String name) { 
 99         try {
100             return super.getResource(name); 
101         } catch (NoClassDefFoundError ncde) { 
102             return this.mainLoader.getResource(name); 
103         } catch (UnsupportedClassVersionError ucve) { 
104             throw new RuntimeException("Bad class " + name, ucve); 
105         } 
106     } 
107 } 

 

The above code extends URLClassloader, trying to load a class from specified url, if not found delegate to its parent <code>mainLoader</code>.

Furthermore the current classloader is replaced (<code>activate()</code>) and afterwards restored (<code>restore()</code>).

 

Example usage would be:

129             DelegatingClassLoader delegateLoader = new DelegatingClassLoader(); 
130             delegateLoader.addUrl(SOMEFILE.toURI().toURL()); 
131  
132             delegateLoader.activate(); 

we create a new loader, add an url (for example from an existing file, and activate the new class loader

 

144             try { 
145                 Class tf = delegateLoader.loadClass( 
146                         "com.myapp.SomeFactory"); 
147  
148                 Method getInstance = tf.getDeclaredMethod("getInstance", null); 
149                 Object factory = getInstance.invoke(null, null); 

afterwards we use reflection to invoke methods ...

 

173             } finally { 
174                 delegateLoader.restore(); 
175             } 

;.. don't forget to restore the old classloader ... 

Posted by peter.grund at 11:32 AM in Uncategorized

 

[Trackback URL for this entry]

Comment: Polprav at Sa, 17 Okt 3:32 PM

Hello from Russia!
Can I quote a post in your blog with the link to you?

Comment: Peter at Di, 20 Okt 9:15 AM

... of course you can ...

Comment: whey.protein.side.effects at Mo, 21 Dez 5:22 PM

Very extraordinary place.
The info here is truly important.

I will refer it to my friends.

Cheers

Comment: fore_xstra_tegy at Mo, 21 Dez 7:38 PM

I am definitely bookmarking this page and sharing it with my friends.

:)

Comment: hmarynka at Fr, 25 Dez 1:56 PM

I want to quote your post in my blog. It can?
And you et an account on Twitter?

Comment: Gaubaribe at Sa, 30 Jan 4:42 AM

Very nice Blog, I will tell my friends about it.

Thanks

Comment: bad creditNowItexunenue at Mi, 10 Feb 9:49 PM

It is a pretty nice site.

I've bookmarked this web site and I am going to notify my friend regarding it.

Thank you

Comment: WP Themes at Sa, 13 Feb 12:10 AM

Genial fill someone in on and this enter helped me alot in my college assignement. Say thank you you on your information.

Your comment:

(not displayed)
 
 
 

Live Comment Preview:

 
« September »
SunMonTueWedThuFriSat
  12345
6789101112
13141516171819
20212223242526
27282930