That's because "user.dir" indicates the current user directory in effect when the JVM is run; in Windows, this is often the location of the JAR unless you specify otherwise. In OSX there may well be no concept of a current dir, but more likely it just has a different default.
Though I have never specifically tested this code under OSX, you can try this to locate the directory from which any class was loaded:
static public File getClassLocation(Class cls, boolean trmjar) {
ClassLoader clsldr; // class loader
URL urlobj; // url object
String exturl; // external form of URL
String lwrurl; // lowercase external form of URL
File rtnfil; // return file
if((clsldr=cls.getClassLoader())==null) { clsldr=ClassLoader.getSystemClassLoader(); }
if((urlobj=clsldr.getResource(cls.getName().replace('.','/')+".class"))==null) {
return null;
}
exturl=urlobj.toExternalForm();
lwrurl=exturl.toLowerCase();
while(lwrurl.startsWith("jar:") || lwrurl.startsWith("file:/")) {
if(lwrurl.startsWith("jar:")) {
if(lwrurl.indexOf("!/")!=-1) { exturl=exturl.substring(4,(exturl.indexOf("!/"))); } // strip encapsulating "jar:" and "!/..." from JAR url
else { exturl=exturl.substring(4 ); } // strip encapsulating "jar:"
}
if(lwrurl.startsWith("file:/")) {
exturl=exturl.substring(6); // strip encapsulating "file:/"
if(!exturl.startsWith("/")) { exturl=("/"+exturl); }
while(exturl.length()>1 && exturl.charAt(1)=='/') { exturl=exturl.substring(1); }
}
lwrurl=exturl.toLowerCase();
}
exturl=java.net.URLDecoder.decode(exturl,"UTF-8");
rtnfil=new File(exturl);
if(lwrurl.endsWith(".class") || (trmjar && lwrurl.endsWith(".jar"))) { rtnfil=rtnfil.getParentFile(); }
if(rtnfil.exists()) { rtnfil=rtnfil.getAbsoluteFile(); }
return rtnfil;
}
it's worked reliably for me for years under Windows for all versions of Java since Java 1.