简体   繁体   中英

Add JarFile to Classpath at runtime in Java 14

Hey how can i add a jar to the classpath at runtime with java 14+? I tried to cast the SystemClassLoader as URLClassLoader as i saw in some examples, but it throws a ClassCastException. Is there anyone who know how i can a the jar to the classpath in newer java versions?

"Add to the system classpath at runtime" is, as a concept, generally unsupported. There can be various unsupported (in that it relies on eg something public being a subclass of something, even though the spec makes no such guarantees) hacks to make that work, but the keyword there is unsupported . There is a very high maintenance burden and should therefore be used only as last resort. In this case, there is no reason to do so; there are far better options available.

ie you are asking an X/Y problem. You have some unstated problem and you thought: I know. I'll add a jar to the classpath at runtime! And now you're asking question about how to do that.

But the error is in the "I know. I'll add a jar to the classpath at runtime" part. That's wrong.

Okay, so what's right?

Simply make a new classloader, that has the system classloader as parent. You're clearly dynamically loading things here, so make sure you do this in the right context. (That is, don't run eg Class.forName("foo.bar") , instead run thatClassLoaderYouMadeForThis.loadClass() instead).

A tricky thing is the following process:

  • A ClassLoader, by default (you can override this default with a custom implementation, but that makes things rather complicated), will first ask its parent loader to load a thing, and will only actually load the class itself if the parent cannot find it.

  • A class will load any of its dependencies (any types that are used inside it) using its own classloader. If that classloader can't find it, you get errors.

In other words, if you have, say, this class:

class MyClassA {
   MyClassB b;
}

as well as class MyClassB extends MyClassA {} , and MyClassA is available on your system classpath (so, can just get loaded), and MyClassB is not, so you are loading it with a child classloader, then that does not work - the act of loading MyClassB will cause MyClassA to be loaded, but as the parent classloader (being the system classloader) does know where to find MyClassA , it becomes MyClassA's loader, and thus it will be asked to load MyClassB in order to make sense of that field it has, and this will fail, as the system loader doesn't know how to do that. But this is quite a bizarre scenario - how did you end up in a scenario where you have a class file ( MyClassA.class ) that was compiled with access to MyClassB , but MyClassB is no longer part of either the same jar file myClassA is in, or in general the same classpath conditions?

So, usually, this isn't a problem, but it's good to be aware of how this works.

With that out of the way:

URLClassLoader myLoader = new URLCLassLoader(new URL[] {
  new URL(Paths.get("/path/to/my/custom/lib.jar").toUri().toURL()});

myLoader.loadClass("com.foo.whateverYouWantedToLoad");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM