如何调用StaticMethodExpr.eval?

时间:2017-02-05 05:18:25

标签: java clojure abstract-syntax-tree

我正在关注this series以了解clojure编译器的工作原理。

我尝试使用以下代码调用eval StaticMethodExpr方法

(ns clojure.lang
  (:use clojure.core)
  (:import [clojure.lang Compiler Compiler$C]))

(def form (read-string "(+ 1 1)") )

(def expr (Compiler/analyze Compiler$C/EXPRESSION form))

(.eval expr)

但没有运气并抛出IllegalArgumentException

Unhandled java.lang.IllegalArgumentException
   Can't call public method of non-public class: public
   java.lang.Object clojure.lang.Compiler$StaticMethodExpr.eval()

我有什么遗漏或者这是a bug in jdk吗?

1 个答案:

答案 0 :(得分:1)

您仍然可以使用反射调用该方法:

(let [m (.getDeclaredMethod clojure.lang.Compiler$Expr "eval" (make-array Class 0))]
  (.setAccessible m true)
  (defn -eval [expr]
    (.invoke m expr (object-array 0))))

(-eval (clojure.lang.Compiler/analyze clojure.lang.Compiler$C/EXPRESSION '(+ 1 2)))
;= 3

如果您的目标是探索,这应该足够好了。

无反射的Java程序可以通过类型(+ 1 2)的引用分析clojure.lang.Compiler.HostExpr来调用此方法,该引用是公共的,即使clojure.lang.Compiler.Expr的声明接口都不是实际的运行时类型也不公开,所以我认为需要setAccessible有点令人惊讶。