classloader with singletom
Hi I am trying to verify that you could have multiple instances of singleton if you use different class loader. Could somebody tell how I can verify . Here is the sample files
publicclass SingletonTest{
privatestatic SingletonTest mSingleton ;
public SingletonTest(){}
privateint x = 0;
publicstatic SingletonTest getInstance(){
if (mSingleton ==null)
mSingleton =new SingletonTest();
return mSingleton;
}
publicvoid setX(int y){
x = y;
}
publicint getX(){return x;}
publicclass SingletonTest{
publicstaticvoid main(String[] args){
System.out.println("another test URL classlodaer");
java.net.URL[] urlsToLoadFrom =new java.net.URL[]{new java.net.URL("file:subdir/")};
URLClassLoader loader1 =new URLClassLoader(urlsToLoadFrom);
URLClassLoader loader2 =new URLClassLoader(urlsToLoadFrom);
Class cls1 = Class.forName("SingletonTest", true, loader1);
Class cls2 = Class.forName("SingletonTest", true, loader2);
Object ob = cls1.newInstance();
SingletonTest t = (SingletonTest)ob;
t = t.getInstance();
System.out.println("reading x:"+t.getX());
ob = cls2.newInstance();
t = (SingletonTest)ob;
t = t.getInstance();
System.out.println("reading x:"+t.getX());
System.out.println("(cls1 == cls2) is " + ((cls1 == cls2) ?"true" :"false"));
}
}
The output is still true. I have used ClassLoader.getSystemClassLoader().loadClass("SingletonTest"); as well
[3111 byte] By [
vpalkondaa] at [2007-10-2 23:35:55]

Sorry you need to use this class for testing
import java.net.URLClassLoader;
public class SingletonTester {
public static void main(String[] args) {
try {
System.out.println("another test URL classlodaer");
java.net.URL[] urlsToLoadFrom = new java.net.URL[]{new java.net.URL("file:subdir/")};
URLClassLoader loader1 = new URLClassLoader(urlsToLoadFrom);
URLClassLoader loader2 = new URLClassLoader(urlsToLoadFrom);
Class cls1 = Class.forName("SingletonTest", true, loader1);
Class cls2 = Class.forName("SingletonTest", true, loader2);
Object ob = cls1.newInstance();
SingletonTest t = (SingletonTest)ob;
t = t.getInstance();
System.out.println("reading x:"+t.getX());
t.setX(2);
System.out.println("setting x to 2 using first classloader's instance");
ob = cls2.newInstance();
t = (SingletonTest)ob;
t = t.getInstance();
System.out.println("reading x:"+t.getX());
System.out.println("(cls1 == cls2) is " + ((cls1 == cls2) ? "true" : "false"));
}catch(Exception e){e.printStackTrace();}
}
}
URLClassLoader loader1 = new URLClassLoader(urlsToLoadFrom, null);
URLClassLoader loader2 = new URLClassLoader(urlsToLoadFrom, null);
Try the above and let us know if it changes the result.
> > URLClassLoader loader1 = new
> URLClassLoader(urlsToLoadFrom, null);
> URLClassLoader loader2 = new
> URLClassLoader(urlsToLoadFrom, null);
>
>
> Try the above and let us know if it changes the
> result.
Should change the results to a ClassCastException :P
What you will have to do is rather tricky. Maybe something like this
public interface ISingleton {
public ISingleton getInstance();
public void setX(int y);
public void getX(int y);
}
public class SingletonTest implements ISingleton {
private static ISingleton mSingleton ;
public SingletonTest(){}
private int x = 0;
public static ISingleton getInstance(){
if (mSingleton == null)
mSingleton = new SingletonTest();
return mSingleton;
}
public void setX(int y) {
x = y;
}
public int getX(){return x;}
}
public class MainClass {
public static void main(String[] args) {
try {
System.out.println("another test URL classlodaer");
java.net.URL[] urlsToLoadFrom = new java.net.URL[]{new java.net.URL("file:subdir/")};
URLClassLoader loader1 = new URLClassLoader(urlsToLoadFrom);
URLClassLoader loader2 = new URLClassLoader(urlsToLoadFrom);
Class cls1 = Class.forName("SingletonTest", true, loader1);
Class cls2 = Class.forName("SingletonTest", true, loader2);
Object ob = cls1.newInstance();
ISingleton t = (ISingleton)ob;
t = t.getInstance();
System.out.println("reading x:"+t.getX());
t.setX(2);
System.out.println("setting x to 2 using first classloader's instance");
ob = cls2.newInstance();
t = (ISingleton)ob;
t = t.getInstance();
System.out.println("reading x:"+t.getX());
System.out.println("(cls1 == cls2) is " + ((cls1 == cls2) ? "true" : "false"));
}catch(Exception e){e.printStackTrace();}
}
}
The class SingletonTest should not be on the regular classpath and is only loadable through the URLClassloader! I think this will work. The problem with the OPs technique is that he has the class he is trying to load present in the class he is loading it into.
SingletonTest t = (SingletonTest)ob;
With his current technique, the presence of that class will cause the main classloader to load it. Then his URLClassloaders will just get the class from the main classloader, IIRC. The fix listed in the other post that sets the parent classloader to null, will mean the URL loader will load the class itself as intended. But then the returned class is not the same as the class its being cast to since its from a different classloader. Solution is to use an interface that can be loaded by both classes.
This technique will work only if SIngletonTest is not present in the main classpath when you execute the program. You need 2 classpaths.
#1 contains MainClass and ISingleton
#2 contains SingletonTest and is loaded by classloader
You can compile them all together at compile time but be sure to split them out at runtime.
> > > > URLClassLoader loader1 = new
> > URLClassLoader(urlsToLoadFrom, null);
> > URLClassLoader loader2 = new
> > URLClassLoader(urlsToLoadFrom, null);
> >
> >
> > Try the above and let us know if it changes the
> > result.
>
> Should change the results to a ClassCastException :P
You are right, my idea was that by breaking the parentage you could get the desired effect. The other way to verify that the Singleton is loaded twice is to make all the calls through reflection.
> Hi I am trying to verify that you could have multiple
> instances of singleton if you use different class
> loader.
I am rather certain that if it doesn't then you have a non-conforming VM.
http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecIX.fm3.html
thanks to all who responded. I made this thing to work. I removed all the code which refers to SingletonTestand checked to see if it loads two different instances. I had to make sure to put the class (the class that is loaded)not in the classpath