在openjdk上运行时,clojure uberjar会抛出错误

时间:2013-06-24 22:58:28

标签: clojure java uberjar

我编写了一个clojure应用程序,它可以选择加密或解密文件,以及源文件名和目标文件名,并执行指定的操作。我使用clojure-1.5.1和oracle的Java SE 7 JDK在运行xubuntu 13的virtualbox vm中开发了应用程序。在这种环境中一切都很好用,但是当我将uberjar复制到使用openjdk / jre 7运行Xubuntu 12.10的主机系统时,就cli解析而言,我得到了一些不同的行为。

1)如果未指定选项,应用程序应打印使用情况标题。这在开发环境下应该正常工作,但在openjdk下,抛出NullPointerException。

2)-v选项应该打印应用程序的构建版本。同样,这在devel环境下工作正常,但在openjdk / Xubuntu-12.10下,抛出异常,说明-v是无效选项。

这是函数(从-main调用):处理cli解析:

(defn parse-cli 
    "Parses command line arguments then calls functions based on those arguments.  Returns a String or nil if successful." 
    [args]
        (let [[opts files banner] 
          (cli args
              ["-h" "--help" "Print this help message." :flag true :default false]
              ["-v" "--version" "Print build number." :flag true :default false]
              ["-e" "--encrypt" "Encrypt source file" :flag true :default false]
              ["-d" "--decrypt" "Decrypt source file" :flag true :default false] 
              ["-k" "--keyfile" "Path to keyfile" :default "./keyfile"])]

            (cond (or (true? (:help opts)) (zero? (count args))) banner
                  (true? (:version opts)) (implementation-version)
                   :else (let [sfile (first files)
                    dfile (second files)
                    cryptoVec (get-cipher-key (:keyfile opts))]

                    (cond (true? (:encrypt opts)) (if (nil? sfile) "No input file specified" 
                                                        (if (nil? dfile) "No outputfile specified." 
                                                            (encrypt-file sfile dfile (first cryptoVec) (second cryptoVec))))
                            (true? (:decrypt opts)) (if (nil? sfile) "No input file specified" 
                                                    (if (nil? dfile) "No outputfile specified." 
                                                            (decrypt-file sfile dfile (first cryptoVec) (second cryptoVec))))
                            :else "No operation specified.")))))

以下是在没有参数的情况下运行uberjar时的完整异常跟踪:

satch@Ziggy-lin:/media/satch/DATA/.crypto$ java -jar cryptfile.jar
Exception in thread "main" java.lang.NullPointerException
    at java.io.FileInputStream.<init>(FileInputStream.java:134)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at clojure.lang.Reflector.invokeConstructor(Reflector.java:180)
at clojure_crypt_file.core$decrypt_file.invoke(core.clj:40)
at clojure_crypt_file.core$_main.doInvoke(core.clj:81)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure_crypt_file.core.main(Unknown Source)

使用-v选项运行应用程序时的跟踪:

satch@Ziggy-lin:/media/satch/DATA/.crypto$ java -jar cryptfile.jar -v
Exception in thread "main" java.lang.Exception: '-v' is not a valid argument
    at clojure.tools.cli$apply_specs.invoke(cli.clj:72)
    at clojure.tools.cli$cli.doInvoke(cli.clj:130)
    at clojure.lang.RestFn.invoke(RestFn.java:486)
    at clojure_crypt_file.core$_main.doInvoke(core.clj:61)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure_crypt_file.core.main(Unknown Source)

其他应用功能在两种环境下均可正常工作。

我认为这些问题是由openjdk7的jre和oracle的SE 7 jre之间的差异引起的,但除此之外我无能为力。具体来说,我想找到一种方法来解决这些差异,如果这确实是问题。

1 个答案:

答案 0 :(得分:0)

好吧,重新编译后,该应用程序现在可以在两种环境中运行。我确实将条件(false?(计数args))更改为(nil?args),但根据文档,这应该以任何方式工作(并且在devel环境中完成)。我没有对-v cli选项做任何事情,但该应用程序现在在两种环境中都表现出相同和正确的行为。这样的事情就是计算机科学是一种爱/恨的原因。 :)