如何从 lein 运行 调试 NullPointerException?
How to debug a NullPointerException from lein run?
我正在尝试创建一个简单的 Clojure 应用程序来解析标准输入 并相应地执行一些命令。我用 lein new app myproject
创建了一个新的 leiningen 项目并将我的代码添加到 src/myproject/core.clj
:
(ns myproject.core
(:require [clojure.string :as str])
(:gen-class))
(def global-vector (ref [{:name "Bob" :age 22} {:name "Alice" :age 21}]))
(defn call [fn_name & fn_args]
(apply (resolve (symbol fn_name)) (map keyword fn_args)))
(defn select
[key]
(dosync
(map #(get % key) @global-vector)))
(defn -main []
(while true
(let [[command cargs] (str/split (read-line) #" ")]
(println (call command cargs)))))
这里要明确的是重现我正在尝试做的事情的步骤:
- 我想从命令行运行这个程序(目前我使用
lein run
)
- 它应该等待用户输入(我使用
read-line
函数)
- 我输入一些文字:
select name
- 我希望程序打印存储在
global-vector
中的名称,但它因 NPE 而崩溃
当 运行 和 lein repl
:
时,一切似乎都按预期工作
myproject.core=> (select :name)
("Bob" "Alice")
myproject.core=> (apply select [:name])
("Bob" "Alice")
myproject.core=> (call "select" "name")
("Bob" "Alice")
myproject.core=> (let [[a b] (str/split "select name" #" ")]
#_=> (println (call a b)))
(Bob Alice)
nil
myproject.core=> (-main)
select name
(Bob Alice)
但是当我 运行 它与 lein run
并输入一些输入时,我得到 NullPointerException
:
$lein run
select name
Syntax error (NullPointerException) compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).
null
Full report at:
/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/clojure-6381054570172229346.edn
报告文件内容如下:
{:clojure.main/message
"Syntax error (NullPointerException) compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).\nnull\n",
:clojure.main/triage
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 125,
:clojure.error/source "form-init2363625704485841211.clj",
:clojure.error/path
"/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj",
:clojure.error/class java.lang.NullPointerException},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message
"Syntax error compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).",
:data
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 125,
:clojure.error/source
"/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj"},
:at [clojure.lang.Compiler load "Compiler.java" 7648]}
{:type java.lang.NullPointerException,
:at [clojure.core$apply invokeStatic "core.clj" 665]}],
:trace
[[clojure.core$apply invokeStatic "core.clj" 665]
[clojure.core$apply invoke "core.clj" 660]
[myproject.core$call invokeStatic "core.clj" 8]
[myproject.core$call doInvoke "core.clj" 7]
[clojure.lang.RestFn invoke "RestFn.java" 423]
[myproject.core$_main invokeStatic "core.clj" 18]
[myproject.core$_main invoke "core.clj" 15]
[clojure.lang.Var invoke "Var.java" 380]
[user$eval140 invokeStatic "form-init2363625704485841211.clj" 1]
[user$eval140 invoke "form-init2363625704485841211.clj" 1]
[clojure.lang.Compiler eval "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7167]
[clojure.lang.Compiler load "Compiler.java" 7636]
[clojure.lang.Compiler loadFile "Compiler.java" 7574]
[clojure.main$load_script invokeStatic "main.clj" 475]
[clojure.main$init_opt invokeStatic "main.clj" 477]
[clojure.main$init_opt invoke "main.clj" 477]
[clojure.main$initialize invokeStatic "main.clj" 508]
[clojure.main$null_opt invokeStatic "main.clj" 542]
[clojure.main$null_opt invoke "main.clj" 539]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]],
:phase :compile-syntax-check}}
我正在尝试了解回溯,但我对 Clojure/Java 环境不熟悉,目前无法辨认。究竟在 Null 值上调用什么?是因为 global-vector
是在 main 之外定义的吗? (但为什么它在 Repl 中有效呢?)
我在 Java 11.0.2 OpenJDK 64 位服务器虚拟机上使用 Clojure 版本:1.10.1.739
和 Leiningen 2.9.4
。
我正在尝试创建一个简单的 Clojure 应用程序来解析标准输入 并相应地执行一些命令。我用 lein new app myproject
创建了一个新的 leiningen 项目并将我的代码添加到 src/myproject/core.clj
:
(ns myproject.core
(:require [clojure.string :as str])
(:gen-class))
(def global-vector (ref [{:name "Bob" :age 22} {:name "Alice" :age 21}]))
(defn call [fn_name & fn_args]
(apply (resolve (symbol fn_name)) (map keyword fn_args)))
(defn select
[key]
(dosync
(map #(get % key) @global-vector)))
(defn -main []
(while true
(let [[command cargs] (str/split (read-line) #" ")]
(println (call command cargs)))))
这里要明确的是重现我正在尝试做的事情的步骤:
- 我想从命令行运行这个程序(目前我使用
lein run
) - 它应该等待用户输入(我使用
read-line
函数) - 我输入一些文字:
select name
- 我希望程序打印存储在
global-vector
中的名称,但它因 NPE 而崩溃
当 运行 和 lein repl
:
myproject.core=> (select :name)
("Bob" "Alice")
myproject.core=> (apply select [:name])
("Bob" "Alice")
myproject.core=> (call "select" "name")
("Bob" "Alice")
myproject.core=> (let [[a b] (str/split "select name" #" ")]
#_=> (println (call a b)))
(Bob Alice)
nil
myproject.core=> (-main)
select name
(Bob Alice)
但是当我 运行 它与 lein run
并输入一些输入时,我得到 NullPointerException
:
$lein run
select name
Syntax error (NullPointerException) compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).
null
Full report at:
/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/clojure-6381054570172229346.edn
报告文件内容如下:
{:clojure.main/message
"Syntax error (NullPointerException) compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).\nnull\n",
:clojure.main/triage
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 125,
:clojure.error/source "form-init2363625704485841211.clj",
:clojure.error/path
"/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj",
:clojure.error/class java.lang.NullPointerException},
:clojure.main/trace
{:via
[{:type clojure.lang.Compiler$CompilerException,
:message
"Syntax error compiling at (/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj:1:125).",
:data
{:clojure.error/phase :compile-syntax-check,
:clojure.error/line 1,
:clojure.error/column 125,
:clojure.error/source
"/private/var/folders/lt/z56f492j3f3gcdf83y4f8x2r0000gn/T/form-init2363625704485841211.clj"},
:at [clojure.lang.Compiler load "Compiler.java" 7648]}
{:type java.lang.NullPointerException,
:at [clojure.core$apply invokeStatic "core.clj" 665]}],
:trace
[[clojure.core$apply invokeStatic "core.clj" 665]
[clojure.core$apply invoke "core.clj" 660]
[myproject.core$call invokeStatic "core.clj" 8]
[myproject.core$call doInvoke "core.clj" 7]
[clojure.lang.RestFn invoke "RestFn.java" 423]
[myproject.core$_main invokeStatic "core.clj" 18]
[myproject.core$_main invoke "core.clj" 15]
[clojure.lang.Var invoke "Var.java" 380]
[user$eval140 invokeStatic "form-init2363625704485841211.clj" 1]
[user$eval140 invoke "form-init2363625704485841211.clj" 1]
[clojure.lang.Compiler eval "Compiler.java" 7177]
[clojure.lang.Compiler eval "Compiler.java" 7167]
[clojure.lang.Compiler load "Compiler.java" 7636]
[clojure.lang.Compiler loadFile "Compiler.java" 7574]
[clojure.main$load_script invokeStatic "main.clj" 475]
[clojure.main$init_opt invokeStatic "main.clj" 477]
[clojure.main$init_opt invoke "main.clj" 477]
[clojure.main$initialize invokeStatic "main.clj" 508]
[clojure.main$null_opt invokeStatic "main.clj" 542]
[clojure.main$null_opt invoke "main.clj" 539]
[clojure.main$main invokeStatic "main.clj" 664]
[clojure.main$main doInvoke "main.clj" 616]
[clojure.lang.RestFn applyTo "RestFn.java" 137]
[clojure.lang.Var applyTo "Var.java" 705]
[clojure.main main "main.java" 40]],
:phase :compile-syntax-check}}
我正在尝试了解回溯,但我对 Clojure/Java 环境不熟悉,目前无法辨认。究竟在 Null 值上调用什么?是因为 global-vector
是在 main 之外定义的吗? (但为什么它在 Repl 中有效呢?)
我在 Java 11.0.2 OpenJDK 64 位服务器虚拟机上使用 Clojure 版本:1.10.1.739
和 Leiningen 2.9.4
。