views:

63

answers:

1

Hello all,

I'm trying to practice myself with custom class loaders, and I've some questions. Is there a way to indicate the JVM to use my custom class loader globally? For example, I wrote small app running under Tomcat 6. The servlet is managed by the container, where should I set my class loader? In addition, the webapp uses some 3rd party jars, can I control the classes loading of those jars?

Are the answers to the above will be different in case of standalone app?

Thanks!

+2  A: 

You can set the system default class loader as a JVM argument:

java -Djava.system.class.loader
    =com.test.YourCustomClassLoader com.test.YourMainClass

As Tomcat starts as a java application, you can set this parameter too, at the %TOMCAT_HOME%\bin\run.bat or $TOMCAT_HOME/bin/run.sh executable.

Edit for completion: If you set your classloader as de System class loader, it will be used to load Tomcat component classes, the different libraries, and your own classes. If you want your class loader to be used only for your application classes (including libraries and so), you should configure a Loader element for your context. The Loader element must be defined inside your Context element, wich can be defined at a context.xml file. More information:

Tomas Narros
For some reason it got me java.lang.Error: java.lang.IllegalStateException: recursive invocation. This is what I did: subclassing ClassLoader, supplying c'tor that take a ClassLoader as parameter, configured it using the -Djava.system.class.loader, and... Boom! Error occurred during initialization of VM :-( Did I miss anything?
Seffy
Without a sight on your code, I can't tell you for sure.
Tomas Narros
I have tested it with a little Main Application I have, and it's run OK.
Tomas Narros
package com.demo.presale;public class MyClassLoader extends ClassLoader{ public MyClassLoader( ClassLoader parent ) { } protected Class loadClass( String name, boolean resolve ) throws ClassNotFoundException { Class c = super.loadClass( name, resolve ); System.out.println( "name: " + name + ", class: " + c); return c; }}
Seffy
And the exception:java.lang.IllegalStateException: recursive invocation at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1312) at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1295) at java.lang.ClassLoader.<init>(ClassLoader.java:228) at com.demo.presale.MyClassLoader.<init>(MyClassLoader.java:7) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
Seffy
In my test code, the overriden Constructor calls the parent class constructor. It checks some permissions, and sets the "initialized" attribute as true. I have also overriden the default constructor, calling the parent constructor too: package com.test; public class MyCustomClassLoader extends ClassLoader { public MyCustomClassLoader() { super(); } public MyCustomClassLoader(ClassLoader parent) { super(parent); } /* rest of the code is quite the same as yours */ }
Tomas Narros
Thanks! It's working now :-)
Seffy