简体   繁体   中英

Loading classes runtime in Java

I would like to make a service, which runs 24/7 and can load new modules or newer version of the already loaded modules without restarting it.

I can load classes from jar files with something like this:

@FunctionalInterface
public interface IWorker {
    void doStuff();
}
IWorker worker;
try {
    URL[] urls = { new URL("jar:file:" +  "C:\\Users\\...\\out\\artifacts\\workers_jar\\somethingworker.jar"  +"!/") };
    ClassLoader cl = new URLClassLoader(urls);
    Class cls = cl.loadClass("hu.test.worker.SomethingWorker");
    worker = (IWorker) cls.newInstance();
    worker.doStuff();
} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}

The software already uses a database table for some configuration for the classes loaded from the modules, so If I store the full classname there (and maybe a path to the jars), I could use this. My question is, can I do this a better way? This is somewhat hard to maintain and can break easily, also I don't know If I can load already loaded classes with it.

Here are some of the things that could break:

  1. Windows could stop you updating the JAR file because Java locks the JAR file while the class loader is active.

  2. Memory leaks. Each time you create a new class loader, you are potentially leaking the previous one. All it needs is for one instance of one class loaded by the previous loader to still be reachable, and you end up with the loader and all classes it loaded being reachable too.

  3. Potential for "strange" behavior because you have two or more classes with the same name. You don't fundamentally break the runtime type system (the JVM is smarter than that) but you find that type casts, etc fail unexpectedly.

  4. If something goes wrong with your redeployment and you need to do a full restart, you are no longer "24 / 7". Same if you redeploy code that has a bug in it and you need to do a full restart to recover.

  5. Occasionally, you will need to upgrade your OS, your Java install, your appserver install ... and other things that will entail (at least) a restart of your service's JVM.

  6. If you have a hardware fault on your server, then your "24 / 7" service goes down.

I would advise that you run two or three instances of your service with (for example) an HA proxy in front. When you want to upgrade, you take down one instances, upgrade it and then "flip" the HA proxy to make the upgraded instance the "primary". Then repeat until all instances are upgraded. If something goes wrong before you have upgraded the last instance, you have the option of flipping back to the old version.

(Implementing this using web containers on a clustered appserver platform is another, equally valid approach.)

Obviously, it is a bit more complicated than this, but running multiple instances of your services is the normal way to achieve high availability. If you can't afford to run multiple instances, then doing clever things to avoid server restarts is not fully addressing the "24 / 7" requirement.

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