How to get the path of a running JAR file?
Asked Answered
A

33

649

My code runs inside a JAR file, say foo.jar, and I need to know, in the code, in which folder the running foo.jar is.

So, if foo.jar is in C:\FOO\, I want to get that path no matter what my current working directory is.

Abusive answered 26/11, 2008 at 12:30 Comment(4)
See Fab's answer for a solution that works when paths include spaces. Also, note that some answers below address the question in the title (jar path), some address the question itself (path of folder containing jar), and some provide paths to classes inside the jar file.Recapitulation
Beware when using in ANT! ============== I call String path = SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getPath(); and get: /C:/apache-ant-1.7.1/lib/ant.jar Not very useful!Spiro
Interesting. The original code in which I used this was never run in ant, so it isn't an issue for me.Abusive
@Dino Fancellu, i experienced exactly what you described. Works during dev, fails when built to jar.Kenakenaf
D
604
return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
    .toURI()).getPath();

Replace "MyClass" with the name of your class.

Obviously, this will do odd things if your class was loaded from a non-file location.

Durant answered 26/11, 2008 at 12:50 Comment(11)
The toURI() step is vital to avoid problems with special characters, including spaces and pluses. The correct one-liner is: return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()); Using URLDecoder does not work for many special characters. See my answer below for further details.Jewish
toURI() seems to break paths run from a network share.Dichroscope
Note: this returns the path including the name of jar fileKenakenaf
Doesn't this point to the jar file, instead of the running directory? You will have to do a on the result getParentFile() for this work.Eldwon
@F.O.O. [A] Yes, it get's point to JAR file [B] No, it has No Relationship to the working directory. Prove this by running java -Duser.dir=TotallyDiffDir -cp [myjarpath] [myappclasspath]: 'user.dir' sets the current working directory, and this answer returns where code is in classpathHavenot
whats the point of the getPath() call? Why not simply construct the File from teh URI?Urien
Also, getProtectionDomain is null if you are getting your class from a stracktrace: val strace = Thread.currentThread().getStackTrace; val path = strace(1).getClass.getProtectionDomainMashburn
Using this method with up to Java 8; placing this method in a class that is in a external Jar, loaded via class-path, then the path of the external jar will be given instead of the actual running Jar.Lichter
this answer have a lot of upvot, I think is because of the date, but now a days this doesn't work, you will get a straigh exception when invoking the new File(URI), .toURI can also be nullSaprogenic
It doesn't work on windows. The path contains a preceding slash, e.g. /c:/documents which is illegal for window file.Flocky
My call to ClassName.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath(); retuns the current working directory (i.e. "."). Has the behavior changed recently? I am using OpenJDK 20.0.1Osterhus
Q
199

Best solution for me:

String path = Test.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");

This should solve the problem with spaces and special characters.

Quadruple answered 27/7, 2011 at 18:22 Comment(11)
One more note: While calling this function from the Jar, the name of the jar is appended at the end for me, therefore had to execute: path.substring(0, path.lastIndexOf("/") + 1);Denominationalism
/ isn't necessarily the path separator. You should do (new File(path)).getParentFile().getPath() instead.Tuscarora
No problems with JAR file name being appended here. The UTF conversion seems to be the perfect solution in combination with @Iviggiani one's (URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");) on Linux. However, I didn't try on Windows.Longoria
Thank you, this allowed me to load files external to my JAR with FileInputStream in both Linux and Windows. Just had to add the decodedpath in front of the filename...Fornax
I regularly package files inside my executable jars (executables, more frequently default settings ) to make little utility tools. The most important thing for me is to have a tool robust, that doesn't need external info and doesn't rely on anything but itself, so this is a great snippet for me! ThanksHoenack
Beware: it is not recommended to use URLDecoder to decode special characters. In particular, characters like + will be erroneously decoded to spaces. See my answer for details.Jewish
This is the best solution(Fab's)... I wrote String path = URLDecoder.decode([MyClass].class.getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8");Regalia
@LilianA.Moraru That's equivalent.Polychromy
This solution also works with a network share, the other answer's used the function toURI(), which cuts off the first part of the share path.Dichroscope
This solution does not work on Windows. The accepted answer works though.Sop
If you use URLDecoder.decode(path, StandardCharsets.UTF_8) introduced in Java 10, you won't have to handle the UnsupportedEncodingException.Wellmeaning
J
176

To obtain the File for a given Class, there are two steps:

  1. Convert the Class to a URL
  2. Convert the URL to a File

It is important to understand both steps, and not conflate them.

Once you have the File, you can call getParentFile to get the containing folder, if that is what you need.

Step 1: Class to URL

As discussed in other answers, there are two major ways to find a URL relevant to a Class.

  1. URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();

  2. URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");

Both have pros and cons.

The getProtectionDomain approach yields the base location of the class (e.g., the containing JAR file). However, it is possible that the Java runtime's security policy will throw SecurityException when calling getProtectionDomain(), so if your application needs to run in a variety of environments, it is best to test in all of them.

The getResource approach yields the full URL resource path of the class, from which you will need to perform additional string manipulation. It may be a file: path, but it could also be jar:file: or even something nastier like bundleresource://346.fwk2106232034:4/foo/Bar.class when executing within an OSGi framework. Conversely, the getProtectionDomain approach correctly yields a file: URL even from within OSGi.

Note that both getResource("") and getResource(".") failed in my tests, when the class resided within a JAR file; both invocations returned null. So I recommend the #2 invocation shown above instead, as it seems safer.

Step 2: URL to File

Either way, once you have a URL, the next step is convert to a File. This is its own challenge; see Kohsuke Kawaguchi's blog post about it for full details, but in short, you can use new File(url.toURI()) as long as the URL is completely well-formed.

Lastly, I would highly discourage using URLDecoder. Some characters of the URL, : and / in particular, are not valid URL-encoded characters. From the URLDecoder Javadoc:

It is assumed that all characters in the encoded string are one of the following: "a" through "z", "A" through "Z", "0" through "9", and "-", "_", ".", and "*". The character "%" is allowed but is interpreted as the start of a special escaped sequence.

...

There are two possible ways in which this decoder could deal with illegal strings. It could either leave illegal characters alone or it could throw an IllegalArgumentException. Which approach the decoder takes is left to the implementation.

In practice, URLDecoder generally does not throw IllegalArgumentException as threatened above. And if your file path has spaces encoded as %20, this approach may appear to work. However, if your file path has other non-alphameric characters such as + you will have problems with URLDecoder mangling your file path.

Working code

To achieve these steps, you might have methods like the following:

/**
 * Gets the base location of the given class.
 * <p>
 * If the class is directly on the file system (e.g.,
 * "/path/to/my/package/MyClass.class") then it will return the base directory
 * (e.g., "file:/path/to").
 * </p>
 * <p>
 * If the class is within a JAR file (e.g.,
 * "/path/to/my-jar.jar!/my/package/MyClass.class") then it will return the
 * path to the JAR (e.g., "file:/path/to/my-jar.jar").
 * </p>
 *
 * @param c The class whose location is desired.
 * @see FileUtils#urlToFile(URL) to convert the result to a {@link File}.
 */
public static URL getLocation(final Class<?> c) {
    if (c == null) return null; // could not load the class

    // try the easy way first
    try {
        final URL codeSourceLocation =
            c.getProtectionDomain().getCodeSource().getLocation();
        if (codeSourceLocation != null) return codeSourceLocation;
    }
    catch (final SecurityException e) {
        // NB: Cannot access protection domain.
    }
    catch (final NullPointerException e) {
        // NB: Protection domain or code source is null.
    }

    // NB: The easy way failed, so we try the hard way. We ask for the class
    // itself as a resource, then strip the class's path from the URL string,
    // leaving the base path.

    // get the class's raw resource path
    final URL classResource = c.getResource(c.getSimpleName() + ".class");
    if (classResource == null) return null; // cannot find class resource

    final String url = classResource.toString();
    final String suffix = c.getCanonicalName().replace('.', '/') + ".class";
    if (!url.endsWith(suffix)) return null; // weird URL

    // strip the class's path from the URL string
    final String base = url.substring(0, url.length() - suffix.length());

    String path = base;

    // remove the "jar:" prefix and "!/" suffix, if present
    if (path.startsWith("jar:")) path = path.substring(4, path.length() - 2);

    try {
        return new URL(path);
    }
    catch (final MalformedURLException e) {
        e.printStackTrace();
        return null;
    }
} 

/**
 * Converts the given {@link URL} to its corresponding {@link File}.
 * <p>
 * This method is similar to calling {@code new File(url.toURI())} except that
 * it also handles "jar:file:" URLs, returning the path to the JAR file.
 * </p>
 * 
 * @param url The URL to convert.
 * @return A file path suitable for use with e.g. {@link FileInputStream}
 * @throws IllegalArgumentException if the URL does not correspond to a file.
 */
public static File urlToFile(final URL url) {
    return url == null ? null : urlToFile(url.toString());
}

/**
 * Converts the given URL string to its corresponding {@link File}.
 * 
 * @param url The URL to convert.
 * @return A file path suitable for use with e.g. {@link FileInputStream}
 * @throws IllegalArgumentException if the URL does not correspond to a file.
 */
public static File urlToFile(final String url) {
    String path = url;
    if (path.startsWith("jar:")) {
        // remove "jar:" prefix and "!/" suffix
        final int index = path.indexOf("!/");
        path = path.substring(4, index);
    }
    try {
        if (PlatformUtils.isWindows() && path.matches("file:[A-Za-z]:.*")) {
            path = "file:/" + path.substring(5);
        }
        return new File(new URL(path).toURI());
    }
    catch (final MalformedURLException e) {
        // NB: URL is not completely well-formed.
    }
    catch (final URISyntaxException e) {
        // NB: URL is not completely well-formed.
    }
    if (path.startsWith("file:")) {
        // pass through the URL as-is, minus "file:" prefix
        path = path.substring(5);
        return new File(path);
    }
    throw new IllegalArgumentException("Invalid URL: " + url);
}

You can find these methods in the SciJava Common library:

Jewish answered 4/10, 2012 at 18:8 Comment(2)
+1; the best answer to date: it will return the path using the correct notation for the OS. (e.g. \ for windows).Leibowitz
Regarding security, I believe I found that Java WebStart did not allow this.Omnipresent
L
70

You can also use:

CodeSource codeSource = YourMainClass.class.getProtectionDomain().getCodeSource();
File jarFile = new File(codeSource.getLocation().toURI().getPath());
String jarDir = jarFile.getParentFile().getPath();
Lynnelynnea answered 14/8, 2011 at 23:33 Comment(3)
This works better for me, cause it gives the path of the Jar, not of the class!Hindbrain
Worked for me too. Combine with Fab's answer and it get better!Marylou
I concur, it's better as it returns the .jar, not the class the .jar calls.Writeoff
I
27

Use ClassLoader.getResource() to find the URL for your current class.

For example:

package foo;

public class Test
{
    public static void main(String[] args)
    {
        ClassLoader loader = Test.class.getClassLoader();
        System.out.println(loader.getResource("foo/Test.class"));
    }
}

(This example taken from a similar question.)

To find the directory, you'd then need to take apart the URL manually. See the JarClassLoader tutorial for the format of a jar URL.

Isiah answered 26/11, 2008 at 12:34 Comment(9)
My JAR file is obfuscated, so this answer does not solve my problem. But I haven't specified that in the question, so this is still a valid answer.Abusive
If it's obfuscated, use Test.class.getName() and do appropriate munging.Isiah
If there are no resources, NPE is thrownEngvall
@WhiteAngel: It shouldn't. I'd expect that to print null instead, as loader.getResource would return null. If you tried to dereference the result instead of passing it to System.out.println, then it would throw an NPE. It's pretty rare that you don't know what resources are available though - and in cases where you don't know that, you can just add a null check in the normal way.Isiah
@JonSkeet So, you think that your solution that works in some particular case is a viable solution?Engvall
@WhiteAngel: I think a solution that works for the question that was asked is fine. Can you give an example where asking the ClassLoader of a class for the resource of that class would return null? That's the question that was being asked. It's not about some arbitrary resource that may or may not be present. (And as I pointed out before, the code I presented wouldn't throw an NPE. If you're seeing one, that would be in some other code that dereferenced the result.)Isiah
@JonSkeet there are so many problems with your answer: 1. There will be no NPE because you didn't answer on the question that was asked (path to JAR dir was asked and you answered on absolutely different question: path to class). 2. As pointed by others, and I got the same issue, it doesn't work for applets. 3. Returned path is not of canonical path representation at all: jar:file:/listener/build/libs/listener-1.0.0-all.jar!/shared/Test.class.Engvall
@WhiteAngel: 1) The last line of my post indicates that you'd need to look at the URL and pick that apart to get the jar file. I agree it's not the most complete answer, but I don't think it's really so bad to be worth arguing about (especially 10 years later...) 2) Applets weren't mentioned in any comments here - strangely enough, I don't have time to look at all comments on all answers on questions that I happened to post an answer to. 3) Again, I link to the format of the jar URL.Isiah
@WhiteAngel: Is it the best answer I've ever written? Nope. Is it as bad as you're making it out to be? No, I don't think so. (Particularly in terms of the claims you made around it throwing an NPE, which it doesn't.) I would suggest you add your own answer instead of making a fuss about this one. That would be a more positive approach.Isiah
A
24

I'm surprised to see that none recently proposed to use Path. Here follows a citation: "The Path class includes various methods that can be used to obtain information about the path, access elements of the path, convert the path to other forms, or extract portions of a path"

Thus, a good alternative is to get the Path objest as:

Path path = Paths.get(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
Anthropogenesis answered 28/8, 2013 at 8:4 Comment(1)
As a note, Path is available starting in Java 7.Tophet
A
17

The only solution that works for me on Linux, Mac and Windows:

public static String getJarContainingFolder(Class aclass) throws Exception {
  CodeSource codeSource = aclass.getProtectionDomain().getCodeSource();

  File jarFile;

  if (codeSource.getLocation() != null) {
    jarFile = new File(codeSource.getLocation().toURI());
  }
  else {
    String path = aclass.getResource(aclass.getSimpleName() + ".class").getPath();
    String jarFilePath = path.substring(path.indexOf(":") + 1, path.indexOf("!"));
    jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8");
    jarFile = new File(jarFilePath);
  }
  return jarFile.getParentFile().getAbsolutePath();
}
Ancipital answered 20/8, 2013 at 17:41 Comment(2)
This will not work. If on Linux, the toUri() method will throw an exception, and you will not reach the else part, for linux.Gertudegerty
broken for anonymous classAdenovirus
M
14

If you are really looking for a simple way to get the folder in which your JAR is located you should use this implementation. Solutions like this are hard to find and many solutions are no longer supported, many others provide the path of the file instead of the actual directory. This is easier than other solutions you are going to find and works for Java version 1.12.

new File(".").getCanonicalPath()

This implementation assumes that the working directory (the one the user is standing when executing the jar) is the same as the executed JAR if this is not the case you can use this other one Gathered from the other answers:

String localPath=new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile().getPath()+"\\"; 

Both will return a String with this format:

"C:\Users\User\Desktop\Folder\"

In a simple and concise line.

Mayenne answered 19/7, 2020 at 10:33 Comment(5)
Is this available only in java 1.12 onwards?Theodoratheodore
No, this will work for older versions as well.Mayenne
The current working directory is not always the same as the executed jar directoryDialogize
new File(".").getCanonicalPath() Will always give you the path where the class (inside the jar) is being executed (called) fromMayenne
The 1st option does not answer the question "How to get the path of a running JAR file?" but only to getting "current working directory". It may or may not be the same.Shantae
H
10

Here's upgrade to other comments, that seem to me incomplete for the specifics of

using a relative "folder" outside .jar file (in the jar's same location):

String path = 
  YourMainClassName.class.getProtectionDomain().
  getCodeSource().getLocation().getPath();

path = 
  URLDecoder.decode(
    path, 
    "UTF-8");

BufferedImage img = 
  ImageIO.read(
    new File((
        new File(path).getParentFile().getPath()) +  
        File.separator + 
        "folder" + 
        File.separator + 
        "yourfile.jpg"));
Highball answered 29/3, 2012 at 11:27 Comment(3)
Beware: it is not recommended to use URLDecoder to decode special characters. In particular, characters like + will be erroneously decoded to spaces. See my answer for details.Jewish
Using special characters in file names is not recommended.Highball
URLDecoder, despite its name, is for decoding URL and form parameter names and values, not URLs.Cacodemon
D
10

I had the the same problem and I solved it that way:

File currentJavaJarFile = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath());   
String currentJavaJarFilePath = currentJavaJarFile.getAbsolutePath();
String currentRootDirectoryPath = currentJavaJarFilePath.replace(currentJavaJarFile.getName(), "");

I hope I was of help to you.

Dambro answered 27/5, 2013 at 14:10 Comment(1)
Don’t do that. URL.getPath() does not return a filename and it will fail in a lot of circumstances, such as file paths with spaces in them.Wenonawenonah
S
10

For getting the path of running jar file I have studied the above solutions and tried all methods which exist some difference each other. If these code are running in Eclipse IDE they all should be able to find the path of the file including the indicated class and open or create an indicated file with the found path.

But it is tricky, when run the runnable jar file directly or through the command line, it will be failed as the path of jar file gotten from the above methods will give an internal path in the jar file, that is it always gives a path as

rsrc:project-name (maybe I should say that it is the package name of the main class file - the indicated class)

I can not convert the rsrc:... path to an external path, that is when run the jar file outside the Eclipse IDE it can not get the path of jar file.

The only possible way for getting the path of running jar file outside Eclipse IDE is

System.getProperty("java.class.path")

this code line may return the living path (including the file name) of the running jar file (note that the return path is not the working directory), as the java document and some people said that it will return the paths of all class files in the same directory, but as my tests if in the same directory include many jar files, it only return the path of running jar (about the multiple paths issue indeed it happened in the Eclipse).

Schoolfellow answered 2/11, 2015 at 8:13 Comment(2)
java.class.path can be multivalued. One those values will certainly provide the directory or JAR file where the current class is located, but which one?Cacodemon
I confirm , I tried other solutions, but never get the jar filename. This works very simply ! thanks - +1Grith
E
7

Other answers seem to point to the code source which is Jar file location which is not a directory.

Use

return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile();
Eldwon answered 10/6, 2016 at 11:57 Comment(1)
It can be a directory, if you're loading your classes from a filesystem instead of a JAR file, e.g. when debugging.Cacodemon
A
4

the selected answer above is not working if you run your jar by click on it from Gnome desktop environment (not from any script or terminal).

Instead, I have fond that the following solution is working everywhere:

    try {
        return URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8");
    } catch (UnsupportedEncodingException e) {
        return "";
    }
Alvaalvan answered 28/9, 2011 at 7:26 Comment(5)
Did you try that in an applet, or an app. launched using Java Web Start? My understanding is that it will fail in both situations (even if the app. is trusted).Leann
This solution can only return the location of "." within the JAR file, not the location of the JAR file.Cacodemon
Beware: it is not recommended to use URLDecoder to decode special characters. In particular, characters like + will be erroneously decoded to spaces. See my answer for details.Jewish
In Spring boot, it will throw NullPointerExceptionBedlamite
You will have NPE if there are no resources in JAR.Engvall
D
4

I had to mess around a lot before I finally found a working (and short) 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();
Dough answered 30/8, 2016 at 13:58 Comment(0)
B
4

For the jar file path:

String jarPath = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
    .toURI()).getPath();

For getting the directory path of that jar file:

String dirPath = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation()
                        .toURI()).getParent();

The results of the two lines above are like this:

/home/user/MyPrograms/myapp/myjar.jar (value of jarPath)

/home/user/MyPrograms/myapp (value of dirPath)

Battles answered 21/11, 2021 at 2:42 Comment(0)
L
3
String path = getClass().getResource("").getPath();

The path always refers to the resource within the jar file.

Lynnett answered 15/11, 2010 at 21:40 Comment(3)
That path string still needs to be simplified to your need. String path = new File(getClass().getResource("").getPath()).getParentFile().getParent(); File jarDir = new File(path.substring(5));Lynnett
Both getResource("") and getResource(".") failed in my tests, when the class resided within a JAR file; both invocations returned null.Jewish
This throws NullPointerException.Cacodemon
P
3
public static String dir() throws URISyntaxException
{
    URI path=Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
    String name= Main.class.getPackage().getName()+".jar";
    String path2 = path.getRawPath();
    path2=path2.substring(1);

    if (path2.contains(".jar"))
    {
        path2=path2.replace(name, "");
    }
    return path2;}

Works good on Windows

Pomfret answered 5/4, 2013 at 10:9 Comment(0)
B
3

I tried to get the jar running path using

String folder = MyClassName.class.getProtectionDomain().getCodeSource().getLocation().getPath();

c:\app>java -jar application.jar

Running the jar application named "application.jar", on Windows in the folder "c:\app", the value of the String variable "folder" was "\c:\app\application.jar" and I had problems testing for path's correctness

File test = new File(folder);
if(file.isDirectory() && file.canRead()) { //always false }

So I tried to define "test" as:

String fold= new File(folder).getParentFile().getPath()
File test = new File(fold);

to get path in a right format like "c:\app" instead of "\c:\app\application.jar" and I noticed that it work.

Benjamin answered 21/2, 2014 at 15:23 Comment(0)
T
3

The simplest solution is to pass the path as an argument when running the jar.

You can automate this with a shell script (.bat in Windows, .sh anywhere else):

java -jar my-jar.jar .

I used . to pass the current working directory.

UPDATE

You may want to stick the jar file in a sub-directory so users don't accidentally click it. Your code should also check to make sure that the command line arguments have been supplied, and provide a good error message if the arguments are missing.

Telestich answered 20/10, 2015 at 16:57 Comment(0)
W
2

Actually here is a better version - the old one failed if a folder name had a space in it.

  private String getJarFolder() {
    // get name and path
    String name = getClass().getName().replace('.', '/');
    name = getClass().getResource("/" + name + ".class").toString();
    // remove junk
    name = name.substring(0, name.indexOf(".jar"));
    name = name.substring(name.lastIndexOf(':')-1, name.lastIndexOf('/')+1).replace('%', ' ');
    // remove escape characters
    String s = "";
    for (int k=0; k<name.length(); k++) {
      s += name.charAt(k);
      if (name.charAt(k) == ' ') k += 2;
    }
    // replace '/' with system separator char
    return s.replace('/', File.separatorChar);
  }

As for failing with applets, you wouldn't usually have access to local files anyway. I don't know much about JWS but to handle local files might it not be possible to download the app.?

Wesley answered 15/4, 2011 at 14:30 Comment(1)
There are several built-in ways to decode the path. No need to write your own code.Cacodemon
L
2

Have tried several of the solutions up there but none yielded correct results for the (probably special) case that the runnable jar has been exported with "Packaging external libraries" in Eclipse. For some reason all solutions based on the ProtectionDomain do result in null in that case.

From combining some solutions above I managed to achieve the following working code:

String surroundingJar = null;

// gets the path to the jar file if it exists; or the "bin" directory if calling from Eclipse
String jarDir = new File(ClassLoader.getSystemClassLoader().getResource(".").getPath()).getAbsolutePath();

// gets the "bin" directory if calling from eclipse or the name of the .jar file alone (without its path)
String jarFileFromSys = System.getProperty("java.class.path").split(";")[0];

// If both are equal that means it is running from an IDE like Eclipse
if (jarFileFromSys.equals(jarDir))
{
    System.out.println("RUNNING FROM IDE!");
    // The path to the jar is the "bin" directory in that case because there is no actual .jar file.
    surroundingJar = jarDir;
}
else
{
    // Combining the path and the name of the .jar file to achieve the final result
    surroundingJar = jarDir + jarFileFromSys.substring(1);
}

System.out.println("JAR File: " + surroundingJar);
Lizzielizzy answered 21/3, 2019 at 11:50 Comment(0)
H
2

Try this:

String path = new File("").getAbsolutePath();
Homing answered 4/7, 2019 at 12:21 Comment(2)
This solution does not work if you're calling on that jar using an absolute command like this: /home/program/java8/bin/java -jar /home/program/myjar.jar It points to /home/ directory instead of jar directory in this case. I tested itBattles
If I'm not mistaken, this just returns the current working directory.Conduct
B
2

This code worked for me to identify if the program is being executed inside a JAR file or IDE:

private static boolean isRunningOverJar() {
    try {
        String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();

        if (pathJar.toLowerCase().contains(".jar")) {
            return true;
        } else {
            return false;
        }
    } catch (Exception e) {
        return false;
    }
}

If I need to get the Windows full path of JAR file I am using this method:

    private static String getPathJar() {
        try {
            final URI jarUriPath =
                    Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
            String jarStringPath = jarUriPath.toString().replace("jar:", "");
            String jarCleanPath  = Paths.get(new URI(jarStringPath)).toString();

            if (jarCleanPath.toLowerCase().contains(".jar")) {
                return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
            } else {
                return null;
            }
        } catch (Exception e) {
            log.error("Error getting JAR path.", e);
            return null;
        }
    }

My complete code working with a Spring Boot application using CommandLineRunner implementation, to ensure that the application always be executed within of a console view (Double clicks by mistake in JAR file name), I am using the next code:

@SpringBootApplication
public class Application implements CommandLineRunner {
    public static void main(String[] args) throws IOException {
        Console console = System.console();

        if (console == null && !GraphicsEnvironment.isHeadless() && isRunningOverJar()) {
            Runtime.getRuntime().exec(new String[]{"cmd", "/c", "start", "cmd", "/k",
                    "java -jar \"" + getPathJar() + "\""});
        } else {
            SpringApplication.run(Application.class, args);
        }
    }

    @Override
    public void run(String... args) {
        /*
        Additional code here...
        */
    }

    private static boolean isRunningOverJar() {
        try {
            String pathJar = Application.class.getResource(Application.class.getSimpleName() + ".class").getFile();

            if (pathJar.toLowerCase().contains(".jar")) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    private static String getPathJar() {
        try {
            final URI jarUriPath =
                    Application.class.getResource(Application.class.getSimpleName() + ".class").toURI();
            String jarStringPath = jarUriPath.toString().replace("jar:", "");
            String jarCleanPath  = Paths.get(new URI(jarStringPath)).toString();

            if (jarCleanPath.toLowerCase().contains(".jar")) {
                return jarCleanPath.substring(0, jarCleanPath.lastIndexOf(".jar") + 4);
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }
}
Bobettebobina answered 22/11, 2019 at 2:12 Comment(0)
U
1

Something that is frustrating is that when you are developing in Eclipse MyClass.class.getProtectionDomain().getCodeSource().getLocation() returns the /bin directory which is great, but when you compile it to a jar, the path includes the /myjarname.jar part which gives you illegal file names.

To have the code work both in the ide and once it is compiled to a jar, I use the following piece of code:

URL applicationRootPathURL = getClass().getProtectionDomain().getCodeSource().getLocation();
File applicationRootPath = new File(applicationRootPathURL.getPath());
File myFile;
if(applicationRootPath.isDirectory()){
    myFile = new File(applicationRootPath, "filename");
}
else{
    myFile = new File(applicationRootPath.getParentFile(), "filename");
}
Unmerciful answered 14/12, 2015 at 6:34 Comment(0)
H
1

Not really sure about the others but in my case it didn't work with a "Runnable jar" and i got it working by fixing codes together from phchen2 answer and another from this link :How to get the path of a running JAR file? The code:

               String path=new java.io.File(Server.class.getProtectionDomain()
                .getCodeSource()
                .getLocation()
                .getPath())
          .getAbsolutePath();
       path=path.substring(0, path.lastIndexOf("."));
       path=path+System.getProperty("java.class.path");
Hypothec answered 21/6, 2016 at 15:57 Comment(0)
A
1

Mention that it is checked only in Windows but i think it works perfect on other Operating Systems [Linux,MacOs,Solaris] :).


I had 2 .jar files in the same directory . I wanted from the one .jar file to start the other .jar file which is in the same directory.

The problem is that when you start it from the cmd the current directory is system32.


Warnings!

  • The below seems to work pretty well in all the test i have done even with folder name ;][[;'57f2g34g87-8+9-09!2#@!$%^^&() or ()%&$%^@# it works well.
  • I am using the ProcessBuilder with the below as following:

🍂..

//The class from which i called this was the class `Main`
String path = getBasePathForClass(Main.class);
String applicationPath=  new File(path + "application.jar").getAbsolutePath();


System.out.println("Directory Path is : "+applicationPath);

//Your know try catch here
//Mention that sometimes it doesn't work for example with folder `;][[;'57f2g34g87-8+9-09!2#@!$%^^&()` 
ProcessBuilder builder = new ProcessBuilder("java", "-jar", applicationPath);
builder.redirectErrorStream(true);
Process process = builder.start();

//...code

🍂getBasePathForClass(Class<?> classs):

    /**
     * Returns the absolute path of the current directory in which the given
     * class
     * file is.
     * 
     * @param classs
     * @return The absolute path of the current directory in which the class
     *         file is.
     * @author GOXR3PLUS[StackOverFlow user] + bachden [StackOverFlow user]
     */
    public static final String getBasePathForClass(Class<?> classs) {

        // Local variables
        File file;
        String basePath = "";
        boolean failed = false;

        // Let's give a first try
        try {
            file = new File(classs.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());

            if (file.isFile() || file.getPath().endsWith(".jar") || file.getPath().endsWith(".zip")) {
                basePath = file.getParent();
            } else {
                basePath = file.getPath();
            }
        } catch (URISyntaxException ex) {
            failed = true;
            Logger.getLogger(classs.getName()).log(Level.WARNING,
                    "Cannot firgue out base path for class with way (1): ", ex);
        }

        // The above failed?
        if (failed) {
            try {
                file = new File(classs.getClassLoader().getResource("").toURI().getPath());
                basePath = file.getAbsolutePath();

                // the below is for testing purposes...
                // starts with File.separator?
                // String l = local.replaceFirst("[" + File.separator +
                // "/\\\\]", "")
            } catch (URISyntaxException ex) {
                Logger.getLogger(classs.getName()).log(Level.WARNING,
                        "Cannot firgue out base path for class with way (2): ", ex);
            }
        }

        // fix to run inside eclipse
        if (basePath.endsWith(File.separator + "lib") || basePath.endsWith(File.separator + "bin")
                || basePath.endsWith("bin" + File.separator) || basePath.endsWith("lib" + File.separator)) {
            basePath = basePath.substring(0, basePath.length() - 4);
        }
        // fix to run inside netbeans
        if (basePath.endsWith(File.separator + "build" + File.separator + "classes")) {
            basePath = basePath.substring(0, basePath.length() - 14);
        }
        // end fix
        if (!basePath.endsWith(File.separator)) {
            basePath = basePath + File.separator;
        }
        return basePath;
    }
Armistice answered 19/5, 2017 at 13:12 Comment(0)
D
1

The above methods didn't work for me in my Spring environment, since Spring shades the actual classes into a package called BOOT-INF, thus not the actual location of the running file. I found another way to retrieve the running file through the Permissions object which have been granted to the running file:


public static Path getEnclosingDirectory() {
    return Paths.get(FileUtils.class.getProtectionDomain().getPermissions()
            .elements().nextElement().getName()).getParent();
}
Depressor answered 17/12, 2020 at 22:46 Comment(1)
Confirmed. This solution works for Spring Boot.Dunc
N
0

This code worked for me:

private static String getJarPath() throws IOException, URISyntaxException {
    File f = new File(LicensingApp.class.getProtectionDomain().().getLocation().toURI());
    String jarPath = f.getCanonicalPath().toString();
    String jarDir = jarPath.substring( 0, jarPath.lastIndexOf( File.separator ));
    return jarDir;
  }
Nick answered 8/9, 2017 at 11:58 Comment(0)
C
-1

The getProtectionDomain approach might not work sometimes e.g. when you have to find the jar for some of the core java classes (e.g in my case StringBuilder class within IBM JDK), however following works seamlessly:

public static void main(String[] args) {
    System.out.println(findSource(MyClass.class));
    // OR
    System.out.println(findSource(String.class));
}

public static String findSource(Class<?> clazz) {
    String resourceToSearch = '/' + clazz.getName().replace(".", "/") + ".class";
    java.net.URL location = clazz.getResource(resourceToSearch);
    String sourcePath = location.getPath();
    // Optional, Remove junk
    return sourcePath.replace("file:", "").replace("!" + resourceToSearch, "");
}
Carswell answered 14/5, 2015 at 18:2 Comment(1)
URL.getPath() does not do what you think it does. Any special characters will be percent-encoded.Wenonawenonah
T
-1

I have another way to get the String location of a class.

URL path = Thread.currentThread().getContextClassLoader().getResource("");
Path p = Paths.get(path.toURI());
String location = p.toString();

The output String will have the form of

C:\Users\Administrator\new Workspace\...

The spaces and other characters are handled, and in the form without file:/. So will be easier to use.

Traitor answered 21/5, 2015 at 18:41 Comment(0)
S
-2

This method, called from code in the archive, returns the folder where the .jar file is. It should work in either Windows or Unix.


  private String getJarFolder() {
    String name = this.getClass().getName().replace('.', '/');
    String s = this.getClass().getResource("/" + name + ".class").toString();
    s = s.replace('/', File.separatorChar);
    s = s.substring(0, s.indexOf(".jar")+4);
    s = s.substring(s.lastIndexOf(':')-1);
    return s.substring(0, s.lastIndexOf(File.separatorChar)+1);
  } 

Derived from code at: Determine if running from JAR

Samalla answered 14/4, 2011 at 18:9 Comment(1)
"It should work in either Windows or Unix." but will fail in any applet and every app. launched using JWS.Leann
E
-2

I write in Java 7, and test in Windows 7 with Oracle's runtime, and Ubuntu with the open source runtime. This works perfect for those systems:

The path for the parent directory of any running jar file (assuming the class calling this code is a direct child of the jar archive itself):

try {
    fooDir = new File(this.getClass().getClassLoader().getResource("").toURI());
} catch (URISyntaxException e) {
    //may be sloppy, but don't really need anything here
}
fooDirPath = fooDir.toString(); // converts abstract (absolute) path to a String

So, the path of foo.jar would be:

fooPath = fooDirPath + File.separator + "foo.jar";

Again, this wasn't tested on any Mac or older Windows

Evvoia answered 3/3, 2014 at 23:54 Comment(0)
R
-4

For something stupid simple, all you need is this one line:

For Windows users, change "pwd" to "cd"

runCommand("pwd");

And just throw this method into the class:

public static String runCommand(String command) {
    StringBuilder sb = new StringBuilder();
    try {
        ProcessBuilder pb = new ProcessBuilder(command);
        final Process p = pb.start();
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        sb.append(br.read());
        while ((line= br.readLine()) != null) sb.append(line).append("\n");
    }
    catch (IOException e) {e.printStackTrace();}
    return sb.toString();
}
Roofing answered 8/4, 2021 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.