15

So far, the examples I have seen for custom ClassLoaders involve subclassing the URLClassLoader, and using that specific instance to load classes in resources.

I have tried in vain to look for alternative methods to replace the SystemClassLoader, so that my ClassLoader can be consulted for classes not located in the classpath.

I tried Thread.currentThread().setContextClassLoader, but it doesn't seem to work.

Is it even possible?

Olaseni
  • 7,698
  • 16
  • 44
  • 68
  • When you say "so that my ClassLoader can be consulted for classes not located in the classpath", do you mean the normal system classes like `java.lang.*` etc or do you mean for loading additional 3rd party classes? – Pacerier Aug 29 '14 at 00:24
  • third party classes ... – Olaseni Aug 29 '14 at 23:52

2 Answers2

13

Though this is an old question, there is indeed a way to replace the system ClassLoader. You might get more than you bargained for, however, with reflection.

        Field scl = ClassLoader.class.getDeclaredField("scl"); // Get system class loader
        scl.setAccessible(true); // Set accessible
        scl.set(null, new YourClassLoader()); // Update it to your class loader

This should work on the Oracle JVM.

Xyene
  • 2,304
  • 20
  • 36
  • 3
    This is of course a hack depending on a private variable that could change between versions of java, but it allowed me to work around problems with one-jar and code in a 3rd party dependency that calls System.getClassLoader() to load a class. Pushing one-jar's class loader up to the to did the trick. – Gus Sep 11 '14 at 07:28
  • @Xyene after I finish with my work - will the application behaviour be alright if I put the classloader back to URLClassLoader.getSystemClassLoader() ? – ha9u63a7 Oct 04 '17 at 16:40
  • 1
    @ha9u63ar I suppose it depends on your use case; if you're not careful it's very likely that your classes will have visibility issues (e.g. class A loaded from the system classloader will not be able to see class B from yours). It's been a few years since I've done anything like that, but there might not be a benefit to putting the system loader back. – Xyene Oct 04 '17 at 17:19
  • 1
    @Xyene I got a linkage error on one of my classes when used in this way. I suppose this solution isn't suitable for webapplication since Servlet container will have it's own classloader and if I cannot reestablish the delegation chain I am in trouble. – ha9u63a7 Oct 04 '17 at 19:20
11

Run JVM with java.system.class.loader property:

java -Djava.system.class.loader=myClassLoader myApplication
Tarlog
  • 10,024
  • 2
  • 43
  • 67
  • 4
    I'm looking for a solution that that precludes modifying the JVM command line – Olaseni Mar 24 '11 at 05:55
  • There is no such solution, if you want to replace the system classloader. You can create in code your proprietary classloader and use it to load the classes, but it will not be a system classloader. Usually creating proprietary classloader is a sufficient solution for most cases. – Tarlog Mar 24 '11 at 08:03
  • https://stackoverflow.com/questions/68380968/java-11-issue-with-adding-dependency-jars-at-runtime - any idea about this issue? – Valsaraj Viswanathan Sep 17 '21 at 13:24