The problem you are experiencing is known as classpath hell.

There is no such functionality in Java. The reason behind this is the design of classloaders, which can only load classes and not unload them. In all likelyhood, this is not going to happen even in the future.

You could use a special classloader to load different classes from different jars, but even this way you quickly stumble into other limitations. For example, a classloader should only load the class if the parent has not yet loaded it. This means that other parts of your code cannot use apache-commons.jar. You could separate your program into two parts and have each run in its own classloader/classpath, but then you'll realize you can't share objects between them anymore. And so on.

In the end, you can either (a) try to find a combination of jars that works with both, (b) fix one part of the program so that it works with the other jar, or (c) break the program into two parts and have each run in separate JVMs.

Answer from jurez on Stack Overflow
Top answer
1 of 5
9

Please find below a snippet as technical example to demonstrate adding / removing a path.

create following source files in any directory

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Stack;
import sun.misc.URLClassPath;

public class EvilPathDemo {

    public static void addPath(String path) throws Exception {
        URL u = new File(path).toURI().toURL();
        URLClassLoader urlClassLoader = (URLClassLoader)
            ClassLoader.getSystemClassLoader();
        Class<?> urlClass = URLClassLoader.class;
        Method method = urlClass.getDeclaredMethod("addURL",
                new Class[]{URL.class}
        );
        method.setAccessible(true);
        method.invoke(urlClassLoader, new Object[]{u});
    }

    public static void removePath(String path) throws Exception {
        URL url = new File(path).toURI().toURL();
        URLClassLoader urlClassLoader = (URLClassLoader) 
            ClassLoader.getSystemClassLoader();
        Class<?> urlClass = URLClassLoader.class;
        Field ucpField = urlClass.getDeclaredField("ucp");
        ucpField.setAccessible(true);
        URLClassPath ucp = (URLClassPath) ucpField.get(urlClassLoader);
        Class<?> ucpClass = URLClassPath.class;
        Field urlsField = ucpClass.getDeclaredField("urls");
        urlsField.setAccessible(true);
        Stack urls = (Stack) urlsField.get(ucp);
        urls.remove(url);
    }

    public static void main(String[] args) throws Exception {
        String parm = args.length == 1 ? args[0] : "";
        String evilPath = "/tmp";

        String classpath = System.getProperty("java.class.path");
        boolean isEvilPathSet = false;
        for (String path : classpath.split(File.pathSeparator)) {
            if (path.equalsIgnoreCase(evilPath)) {
                System.out.printf("evil path '%s' in classpath%n", evilPath);
                isEvilPathSet = true;
                break;
            }
        }
        if (isEvilPathSet && parm.equalsIgnoreCase("REMOVE")) {
            System.out.printf("evil path '%s' will be removed%n", evilPath);
            removePath(evilPath);
        }
        tryToLoad("Foo");
        if (parm.equalsIgnoreCase("ADD")) {
            System.out.printf("evil path '%s' will be added%n", evilPath);
            addPath(evilPath);
        }
        tryToLoad("Bar");
    }

    private static void tryToLoad(String className) {
        try {
            Class<?> foo = Class.forName(className);
            System.out.printf("class loaded: %s%n", foo.getName());
        } catch (ClassNotFoundException ex) {
            System.out.println(ex);
        }
    }
}

.

public class Foo {
    static {
        System.out.println("I'm foo...");
    }
}

.

public class Bar {
    static {
        System.out.println("I'm bar...");
    }
}

compile them as follow

javac EvilPathDemo.java
javac -d /tmp Foo.java Bar.java

During the test we will try to load the classes Foo and Bar.

without /tmp in the classpath

java -cp . EvilPathDemo
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar

adding /tmp to the classpath

java -cp . EvilPathDemo add
java.lang.ClassNotFoundException: Foo
evil path '/tmp' will be added
I'm bar...
class loaded: Bar

with /tmp in the classpath

java -cp .:/tmp EvilPathDemo
evil path '/tmp' in the classpath
I'm foo...
class loaded: Foo
I'm bar...
class loaded: Bar

remove /tmp from the classpath

java -cp .:/tmp EvilPathDemo remove
evil path '/tmp' in the classpath
evil path '/tmp' will be removed
java.lang.ClassNotFoundException: Foo
java.lang.ClassNotFoundException: Bar

During the testing I found out that following cases are not working.

  • addPath(evilPath);
    tryToLoad("Foo");
    removePath(evilPath); // had not effect
    tryToLoad("Bar");
  • removePath(evilPath);
    tryToLoad("Foo");
    addPath(evilPath); // had no effect
    tryToLoad("Bar");
  • tryToLoad("Foo");
    removePath(evilPath); // had no effect
    tryToLoad("Bar");

I did not spent time to find out why. Because I don't see any practical use in it. If you really need/wish to play with the classpaths have a look how classloaders are working.

2 of 5
4

The removePath method from above did not work for me and my Weld Container, the url stack was always emtpy. The following ugly smugly method worked:

public static void removeLastClasspathEntry() throws Exception {
    URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class<?> urlClass = URLClassLoader.class;
    Field ucpField = urlClass.getDeclaredField("ucp");
    ucpField.setAccessible(true);
    URLClassPath ucp = (URLClassPath) ucpField.get(urlClassLoader);

    Field loadersField = URLClassPath.class.getDeclaredField("loaders");
    loadersField.setAccessible(true);
    List jarEntries = (List) loadersField.get(ucp);
    jarEntries.remove(jarEntries.size() - 1);

    Field pathField = URLClassPath.class.getDeclaredField("path");
    pathField.setAccessible(true);
    List pathList = (List) pathField.get(ucp);
    URL jarUrl = (URL) pathList.get(pathList.size() - 1);
    String jarName = jarUrl.toString();
    pathList.remove(pathList.size() - 1);

    Field lmapField = URLClassPath.class.getDeclaredField("lmap");
    lmapField.setAccessible(true);
    Map lmapMap = (Map) lmapField.get(ucp);
    lmapMap.remove(jarName.replaceFirst("file:/", "file:///"));
}
Discussions

java - Eclipse- How to remove jars which are added "from class path" of referenced library - Stack Overflow
I use eclipse. I just added two jars into my project as library >Add external jar . As in below picture, all other jars in the folder are coming to my project as referenced library. How to remove t... More on stackoverflow.com
🌐 stackoverflow.com
dynamic - How to exclude a specific jar from java classpath - Stack Overflow
I am using this below structure to set classpath in my java application. How can I exclude a specific jar that is loading in runtime. #!/bin/sh export JAVA_HOME=/usr/local/java PATH=/usr/local/jav... More on stackoverflow.com
🌐 stackoverflow.com
java - Dynamically removing jars from classpath - Stack Overflow
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 the... More on stackoverflow.com
🌐 stackoverflow.com
How to remove .jar files/locations from CLASSPATH?
Delete the line that contains the path for java in each file. More on reddit.com
🌐 r/learnjava
1
4
October 5, 2020
🌐
Gradle
discuss.gradle.org › help/discuss
Exclude library from Java Classpath - Help/Discuss - Gradle Forums
July 8, 2016 - I have a multiproject and have a compile error that a symbol cannot be found from a StringUtils class. Obviously i have several StringUtils classes on the classpath, one from the hibernate package, another from some ant …
🌐
JetBrains
youtrack.jetbrains.com › issue › KT-41664
Remove the "runtime JAR files in the classpath should have the same version" warning : KT-41664
Learn more With your consent, JetBrains may also use cookies and your IP address to collect individual statistics and provide you with personalized offers and ads subject to the Privacy Notice and the Terms of Use. JetBrains may use third-party services for this purpose. You can adjust or withdraw your consent at any time by visiting the Opt-Out. ... w: Runtime JAR files in the classpath should have the same version.
🌐
Stack Overflow
stackoverflow.com › questions › 44798158 › how-to-exclude-a-specific-jar-from-java-classpath
dynamic - How to exclude a specific jar from java classpath - Stack Overflow
#!/bin/sh export JAVA_HOME=/usr/local/java PATH=/usr/local/java/bin:${PATH} cd /home/ala/DevDaily/Musubi THE_CLASSPATH= for i in `ls ./lib/*.jar` do THE_CLASSPATH=${THE_CLASSPATH}:${i} done ...
🌐
AGI
help.agi.com › STKParallelComputingServerAPIJava › html › 2775c950-2139-11e3-8224-0800200c9a66.htm
Include or remove additional third party libraries - Agi
Jobs are executed in separate JVMs and third-party libraries are often needed in tasks. Java jar dependencies are automatically sent by default. Although this works in many cases, there are times when jars need to be manually added or removed. For instance, in many java application servers the value of the java.class.path property does not contain the jars that are needed for the task.
🌐
Talend
community.talend.com › s › question › 0D53p00007vCsShCAK › helpremove-libraries-from-class-path
Home | Qlik Community
Qlik Community is the global online community for Qlik employees, experts, customers, partners, developers and evangelists to collaborate.
Find elsewhere
🌐
UPenn SEAS
seas.upenn.edu › ~cis1xx › resources › java › jar › jarindrjava.html
Adding and Removing JAR files in DrJava
A JAR file is a way of storing many (pre-compiled) Java classes. Below are instructions for adding and removing jar files from DrJava's resource locations.
🌐
Tabnine
tabnine.com › home › code library
Code Library - Tabnine
July 25, 2024 - Get the answers and suggestions you need from our AI code assistant. Get started in minutes with a free 90 day trial of Tabnine Pro.
🌐
Eclipse
bugs.eclipse.org › bugs › show_bug.cgi
318160 – Impossible to remove referenced library - Bugs
June 28, 2010 - Download · Getting Started · Members · Projects · Community · Marketplace · Events · Planet Eclipse · Videos · Participate
🌐
Coderanch
coderanch.com › t › 377993 › java › find-remove-unwanted-jars-classpath
find/remove unwanted jars from classpath (Java in General forum at Coderanch)
Hi, I don't know the direct way/ single step way, But one way is through eclipse Remove all the jars from the eclipse It will start showing red lines for missing classes. Add the missing package, and continue till there are not redlines in the file Definitely , not the best option, but this can be the way Thanks ... The "project classpath"?
🌐
Oracle
docs.oracle.com › cd › E14545_01 › help › oracle.eclipse.tools.weblogic.doc › html › j2eelib › operations › opRemoveLibRefFromClasspath.html
Removing a library reference from the project classpath
Right-click on the project in the Project Explorer view and select Properties from the drop-down menu.This will open the Propertis dialog. On the Propertis dialog, select the Java Build Path from the list of properties. On the Java Build Path part of the dialog, select the Libraries tab.
🌐
Stack Overflow
stackoverflow.com › questions › 17349335 › can-a-directory-be-removed-from-the-class-path-at-runtime
java - Can a directory be removed from the class path at runtime? - Stack Overflow
It is possible to add a path to the classpath dynamically, see Can a directory be added to the class path at runtime?. My question is the opposite: is it possible to remove a directory from the cl...