【问题标题】:How to access a default access method using interop in Clojure?如何在 Clojure 中使用互操作访问默认访问方法?
【发布时间】:2015-09-13 06:40:43
【问题描述】:

我正在 Clojure REPL 上执行以下操作:

user=> (ns clojure.lang)
nil
clojure.lang=> (def tran (clojure.lang.LockingTransaction.))
#'clojure.lang/tran
clojure.lang=> (.getReadPoint tran)

这给出了以下结果:

IllegalArgumentException No matching field found: getReadPoint for class clojure.lang.LockingTransaction  clojure.lang.Reflector.getInstanceField (Reflector.java:271)

现在这个方法does exist

现在我认为我应该能够从 REPL 访问默认访问方法。

我的问题是:如何在 Clojure 中使用互操作访问默认访问方法?

【问题讨论】:

    标签: clojure


    【解决方案1】:

    这是可能的,但它需要一些肮脏的技巧。

    有一个奇怪的库,vinyasa,它让这些技巧更容易被拉取。

    这是使用这个奇怪库的 repl 会话的记录:

    user=> (require '[vinyasa.inject :as inject])
    nil
    user=> (inject/in clojure.core [vinyasa.reflection .> .? .* .% .%> .& .>ns .>var])
    []
    user=> (def locking-transaction (clojure.lang.LockingTransaction.))
    #'user/locking-transaction
    user=> (def get-read-point (.? clojure.lang.LockingTransaction "getReadPoint"))
    #'user/get-read-point
    user=> get-read-point
    (#[getReadPoint :: (clojure.lang.LockingTransaction) -> void])
    user=> ((first get-read-point) locking-transaction)
    nil
    

    在这里我们加载vinyasa,并按照库的建议,将其奇怪命名的宏注入clojure.core。使用.? 宏,我们找到了虚拟机通常会阻止我们访问的受保护方法,并通过反射获得可用于绕过虚拟机安全性的版本。最后我们访问并调用LockingTransaction对象上的方法,得到预期的返回值(nil)。

    请注意,在 Clojure 中将符号插入到其他命名空间中不被视为正常或可取的行为,也不会绕过 VM 保护,您可以通过反射调用受保护或私有方法轻松地对 VM 进行分段或导致非常奇怪的错误。

    【讨论】:

    • ">虚拟机通常会阻止我们访问" ...如果您在同一个命名空间中 - 您不能访问默认访问字段吗?
    • 谢谢 - Chris Zheng 是一位传奇的 Clojure 程序员。
    • @hawkeye 命名空间与包不同
    • @noisesmith - 我不认为这很奇怪 =)
    猜你喜欢
    • 2015-10-06
    • 2010-10-12
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多