Solution 1:

Update

Since it doesn't work in certain test-cases, I'll update the answer.

The correct way to do this should be with ClassLoader:

File jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath());
System.out.println(jarDir.getAbsolutePath());

Tested on various classpaths, the output was correct.


Old answer

This should work

File f = new File(System.getProperty("java.class.path"));
File dir = f.getAbsoluteFile().getParentFile();
String path = dir.toString();

It works for me, my program is in:

C:\Users\User01\Documents\app1\dist\JavaApplication1.jar

And it returns

C:\Users\User01\Documents\app1\dist

Solution 2:

Herewith my version of computing the jar directory

/**
 * Compute the absolute file path to the jar file.
 * The framework is based on http://stackoverflow.com/a/12733172/1614775
 * But that gets it right for only one of the four cases.
 * 
 * @param aclass A class residing in the required jar.
 * 
 * @return A File object for the directory in which the jar file resides.
 * During testing with NetBeans, the result is ./build/classes/,
 * which is the directory containing what will be in the jar.
 */
public static File getJarDir(Class aclass) {
    URL url;
    String extURL;      //  url.toExternalForm();

    // get an url
    try {
        url = aclass.getProtectionDomain().getCodeSource().getLocation();
          // url is in one of two forms
          //        ./build/classes/   NetBeans test
          //        jardir/JarName.jar  froma jar
    } catch (SecurityException ex) {
        url = aclass.getResource(aclass.getSimpleName() + ".class");
        // url is in one of two forms, both ending "/com/physpics/tools/ui/PropNode.class"
        //          file:/U:/Fred/java/Tools/UI/build/classes
        //          jar:file:/U:/Fred/java/Tools/UI/dist/UI.jar!
    }

    // convert to external form
    extURL = url.toExternalForm();

    // prune for various cases
    if (extURL.endsWith(".jar"))   // from getCodeSource
        extURL = extURL.substring(0, extURL.lastIndexOf("/"));
    else {  // from getResource
        String suffix = "/"+(aclass.getName()).replace(".", "/")+".class";
        extURL = extURL.replace(suffix, "");
        if (extURL.startsWith("jar:") && extURL.endsWith(".jar!"))
            extURL = extURL.substring(4, extURL.lastIndexOf("/"));
    }

    // convert back to url
    try {
        url = new URL(extURL);
    } catch (MalformedURLException mux) {
        // leave url unchanged; probably does not happen
    }

    // convert url to File
    try {
        return new File(url.toURI());
    } catch(URISyntaxException ex) {
        return new File(url.getPath());
    }
}

Solution 3:

I had to mess around a lot before I finally found a working solution.
It is possible that the jarLocation comes with a prefix like file:\ or jar:file\, which can be removed by using String#substring().

URL jarLocationUrl = MyClass.class.getProtectionDomain().getCodeSource().getLocation();
String jarLocation = new File(jarLocationUrl.toString()).getParent();

Solution 4:

If you know

file(Server.class.getProtectionDomain().getCodeSource().getLocation().getPath());

returns

C:\Users\Kevin\Desktop\server.jar/server/Server

And you know your Jar name is server.jar or for matter any .jar file, your intention is to get C:\Users\Kevin\Desktop , straight forward way is to do string manipulation.

With the retrieved output, tokenize the string based on File.separator and construct the path (by concatenating the strings with File.separator in between) until you get a token which contains .jar