JavaUser
JavaUser

Reputation: 33

Dynamically removing jars from classpath

I have a requirement where jars have to be changed based on distribution where distribution is captured from UI.

Distribution varies from one group to another. If a distribution is selected then jars related to that distribution have to be added to the class-path dynamically/programmatically.

If another distribution is selected then the previous jars which were added to the class-path have to be removed from class-path dynamically and new jars related to new distribution have to be added dynamically.The same has to be continued for other distributions.

I have seen earlier threads which state that adding jars at run-time is possible through Class Loader but I haven't seen any thread where jars can be removed dynamically from class-path.

Can anyone suggest whether this is possible?

Upvotes: 2

Views: 2292

Answers (1)

Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 299048

A naive approach would be a ClassLoader that delegates to distribution-specific ClassLoaders. Here's a rough draft of such a class:

public class DistributionClassLoader extends ClassLoader {

    public DistributionClassLoader(ClassLoader parent) {
        super(parent);
    }

    private Map<String, ClassLoader> classLoadersByDistribution =
            Collections.synchronizedMap(new WeakHashMap<>());

    private final AtomicReference<String> distribution = new AtomicReference<>();

    @Override
    protected Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException {
        final ClassLoader delegate = classLoadersByDistribution.get(distribution.get());
        if (delegate != null) return Class.forName(name, true, delegate);
        throw new ClassNotFoundException(name);
    }

    public void addDistribution(String key, ClassLoader distributionClassLoader){
        classLoadersByDistribution.put(key,distributionClassLoader);
    }
    public void makeDistributionActive(String key){distribution.set(key);}
    public void removeDistribution(String key){
        final ClassLoader toRemove = classLoadersByDistribution.remove(key);
    }
}

Several problems remain, however: when switching distributions, we'd want to unload all classes from the previous distribution. I see no way to achieve that. Also: if you have any references to objects created by the delegate ClassLoaders, these objects will keep references to their ClassLoaders. I'm not sure there is a proper solution, but this may get you started.

Upvotes: 1

Related Questions