41

I've created an executable jar and using commons-cli to give the user the ability to specify command line parameters when he launches the client. Everything works fine. However, when I print the usage statement for the jar, I would like to show the following:

usage: java -jar myprog.jar <options> <file>
--help Display the help message
--debug Enable debugging
....

Printing of all the options is easily done with commons-cli. However, the "usage" line is the head scratcher. I cannot seem to figure out a way to get the "myprog.jar" name from the args[] that are passed to the application.

Is there any easy way of doing this? I could use a pretty convoluted method to back trace from my class' classloader and figure out if it is contained within a jar, but that seems like a fairly ugly answer to what should be a pretty simple question.

private String getPath(Class cls) {
 String cn = cls.getName();
 String rn = cn.replace('.', '/') + ".class";
 String path =
 getClass().getClassLoader().getResource(rn).getPath();
 int ix = path.indexOf("!");
 if(ix >= 0) {
 return path.substring(0, ix);
 } else {
 return path;
 }
}
asked Jun 22, 2012 at 14:30
2
  • tried stackoverflow.com/questions/320542/… ? Commented Jun 22, 2012 at 14:43
  • I did see that link already, but it looked as though it was almost a "hack" as well. I cannot believe that there is not a more direct solution. Additionally, the API states that "getCodeSource()" may return null, but does not elaborate under which conditions, so I naturally wondered if this was a "fail-safe" method to use. Commented Jun 22, 2012 at 15:03

2 Answers 2

62

Here you go:

new java.io.File(SomeClassInYourJar.class.getProtectionDomain()
 .getCodeSource()
 .getLocation()
 .getPath())
.getName()

Edit: I saw your comment about getSourceCode API. Well, this is probably the best you can do in Java. About getCodeSource() returning null, I think it mainly happens on classes in java.lang.* and other special classes for which the source location is "hidden". Should work for your own classes though.

answered Jun 22, 2012 at 15:35
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks - that's the same thing that @Charles pointed to in the SO link. My biggest concern as I mentioned above is that the api for getCodeSource() indicates that it can be null, but does not elaborate under which conditions.
The other problem with this is that it does not take into account the fact that the class file may be nested within archives. So I would still need to check for a ! substring. Like I said, it seems a little clunky and am quite surprised that Java does not have a better solution.
It's mostly because there is rarely a reason to know the name of the jar file you're running from. The functionality should (ideally) be independent of the name.
@rodion for me the above is giving classes! as output
Any idea if this technique will translate to GraalVM AOTC? I'd like to create a multicall binary.
2

You should in any case add a .toURI() before you call getPath(). Thats because of some quirks in java's URL implementation - see how to encode URL to avoid special characters in java for details.

answered Mar 10, 2014 at 9:59

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.