2

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?

Mark O'Connor
  • 76,015
  • 10
  • 139
  • 185
JavaUser
  • 33
  • 9
  • @Sean Patrick Floyd The question is not duplicate as the link which you have provided doesn't address solution to the problem.The solution in your link gives an explanation of how a class has to be loaded from an existing jar in class-path.But the present problem is I have to add a new jar to the class-path altogether dynamically and remove an existing jar from the class-path programmatically for which I couldn't find any solution in any thread. – JavaUser Dec 18 '15 at 07:20
  • reopened, let's see where this goes – Sean Patrick Floyd Dec 18 '15 at 08:21
  • Have you considered OSGi ? – Svetlin Zarev Dec 19 '15 at 09:52

1 Answers1

1

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.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588