Clojure:如何获取正在运行的JAR /根源目录的路径?

时间:2012-03-14 01:33:31

标签: path jar clojure

在Java中有一个simple way来获取正在运行的jar文件的路径:

MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath()

但在Clojure中,我们没有类名,只有名称空间和函数。同样的事情适用于未编译的脚本/ REPL。

所以我的问题是:

  1. 我们如何找到正在运行的jar文件的路径
  2. 我们如何找到未编译源文件的路径

6 个答案:

答案 0 :(得分:8)

默认情况下,类的名称是AOT编译的命名空间的名称(这是gen-class的用途),因此您只需使用命名空间的类。

(ns foo.core
  (:gen-class))

(defn this-jar
  "utility function to get the name of jar in which this function is invoked"
  [& [ns]]
  ;; The .toURI step is vital to avoid problems with special characters,
  ;; including spaces and pluses.
  ;; Source: https://stackoverflow.com/q/320542/7012#comment18478290_320595
  (-> (or ns (class *ns*))
      .getProtectionDomain .getCodeSource .getLocation .toURI .getPath))

(defn -main [& _]
  (println (this-jar foo.core)))

跑步结果:

$ java -cp foo-0.1.0-SNAPSHOT-standalone.jar foo.core
/home/rlevy/prj/foo/target/foo-0.1.0-SNAPSHOT-standalone.jar

答案 1 :(得分:2)

classpath的想法是隐藏类的来源。您可能从不同的类加载器中加载了具有相同名称的类,您可能在多个jar中具有相同的类,并依赖类路径排序来选择正确的类。

你为什么想知道?如果出于调试/记录目的之外的任何其他原因,您处于危险的境地并应谨慎行事。

事实上,没有jar文件的类是完全合理的。对于任何运行时生成的类(思考代理),这可能发生在java中。

在clojure中,一个简单的例子如下面的repl会话所示......你会看到@mikera的建议适用于clojure.lang.Atom这是一个内置类。但是当你使用deftype创建自己的类型时,clojure会生成一个类,它没有位置......

user> (prn (-> clojure.lang.Atom 
               (.getProtectionDomain) 
               (.getCodeSource) 
               (.getLocation)))
#<URL file:/workspace/clj-scratch/lib/clojure-1.3.0.jar>
nil
user> (deftype Foo [])
user.Foo
user> (prn (-> (Foo.)
               (.getClass)
               (.getProtectionDomain)
               (.getCodeSource)
               (.getLocation)))
nil
nil
user> 

答案 2 :(得分:1)

我没试过这个,但看起来你需要的只是一个类实例。例如,你可以不这样做:

(-> (new Object) (.getClass) (.getProtectionDomain) (.getCodeSource) (.getLocation) (.getPath))

答案 3 :(得分:1)

您可以尝试从Clojure本身定义的类中获取路径,例如:

(-> clojure.lang.Atom (.getProtectionDomain) (.getCodeSource) (.getLocation))

=> file:/some/path/to/clojure-1.3.0.jar

我相信如果您在REPL上运行Clojure脚本或编码,这在技术上就是正在运行的jar文件。

答案 4 :(得分:1)

(defn this-jar
  "utility function to get the name of jar in which this function is invoked"
  [& [ns]]
  (-> (or ns (class *ns*))
      .getProtectionDomain .getCodeSource .getLocation .toURI .getPath))

请注意,调用.toURI以避免出现具有空格的路径问题至关重要,如同等Java问题中所述:How to get the path of a running JAR file?

答案 5 :(得分:0)

在jar中查找源文件:tools.namespace/clojure-sources-in-jar