2017-06-20 30 views
0

我有一个由Protocol Buffers生成的名为TextLine的Java类。当我实例化的Java对象:clojure.java.data中的java.lang.StackOverflowError from-java

(def tb (-> (TextLine/newBuilder) (.setText "this is a text line") (.build))) 

然后调用:

(from-java tb) 

我收到的StackOverflowError:

java.lang.StackOverflowError: null 
at java.lang.Class.getMethods (Class.java:1614) 
clojure.lang.Reflector.getMethods (Reflector.java:373) 
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:311) 
clojure.java.data$add_getter_fn.invokeStatic (data.clj:38) 
clojure.java.data$add_getter_fn.invoke (data.clj:37) 
clojure.core.protocols$fn__6755.invokeStatic (protocols.clj:167) 
clojure.core.protocols/fn (protocols.clj:124) 
clojure.core.protocols$fn__6710$G__6705__6719.invoke (protocols.clj:19) 
clojure.core.protocols$seq_reduce.invokeStatic (protocols.clj:31) 
clojure.core.protocols$fn__6732.invokeStatic (protocols.clj:75) 
clojure.core.protocols/fn (protocols.clj:75) 
clojure.core.protocols$fn__6684$G__6679__6697.invoke (protocols.clj:13) 
clojure.core$reduce.invokeStatic (core.clj:6545) 
clojure.core$reduce.invoke (core.clj:6527) 
clojure.java.data$eval554$fn__555.invoke (data.clj:135) 
clojure.lang.MultiFn.invoke (MultiFn.java:229) 
clojure.java.data$make_getter_fn$fn__501.invoke (data.clj:35) 
clojure.java.data$eval554$fn__555$iter__556__560$fn__561.invoke (data.clj:136) 
clojure.lang.LazySeq.sval (LazySeq.java:40) 
clojure.lang.LazySeq.seq (LazySeq.java:49) 
clojure.lang.Cons.next (Cons.java:39) 
clojure.lang.RT.next (RT.java:688) 
clojure.core$next__4341.invokeStatic (core.clj:64) 
clojure.core.protocols$fn__6755.invokeStatic (protocols.clj:168) 
clojure.core.protocols/fn (protocols.clj:124) 
clojure.core.protocols$fn__6710$G__6705__6719.invoke (protocols.clj:19) 
clojure.core.protocols$seq_reduce.invokeStatic (protocols.clj:31) 
clojure.core.protocols$fn__6738.invokeStatic (protocols.clj:75) 
clojure.core.protocols/fn (protocols.clj:75) 
clojure.core.protocols$fn__6684$G__6679__6697.invoke (protocols.clj:13) 
clojure.core$reduce.invokeStatic (core.clj:6545) 
clojure.core$into.invokeStatic (core.clj:6610) 
clojure.core$into.invoke (core.clj:6604) 
clojure.java.data$eval554$fn__555.invoke (data.clj:136) 
clojure.lang.MultiFn.invoke (MultiFn.java:229) 
clojure.java.data$make_getter_fn$fn__501.invoke (data.clj:35) 
clojure.java.data$eval554$fn__555$iter__556__560$fn__561.invoke (data.clj:136) 
clojure.lang.LazySeq.sval (LazySeq.java:40) 
clojure.lang.LazySeq.seq (LazySeq.java:49) 
clojure.lang.Cons.next (Cons.java:39) 
clojure.lang.RT.next (RT.java:688) 
clojure.core$next__4341.invokeStatic (core.clj:64) 
clojure.core.protocols$fn__6755.invokeStatic (protocols.clj:168) 
clojure.core.protocols/fn (protocols.clj:124) 
clojure.core.protocols$fn__6710$G__6705__6719.invoke (protocols.clj:19) 
clojure.core.protocols$seq_reduce.invokeStatic (protocols.clj:31) 
clojure.core.protocols$fn__6738.invokeStatic (protocols.clj:75) 
clojure.core.protocols/fn (protocols.clj:75) 
clojure.core.protocols$fn__6684$G__6679__6697.invoke (protocols.clj:13) 
clojure.core$reduce.invokeStatic (core.clj:6545) 
clojure.core$into.invokeStatic (core.clj:6610) 
clojure.core$into.invoke (core.clj:6604) 
clojure.java.data$eval554$fn__555.invoke (data.clj:136) 
clojure.lang.MultiFn.invoke (MultiFn.java:229) 
clojure.java.data$make_getter_fn$fn__501.invoke (data.clj:35) 
clojure.java.data$eval554$fn__555$iter__556__560$fn__561.invoke (data.clj:136) 
clojure.lang.LazySeq.sval (LazySeq.java:40) 
clojure.lang.LazySeq.seq (LazySeq.java:49) 
clojure.lang.Cons.next (Cons.java:39) 
clojure.lang.RT.next (RT.java:688) 
clojure.core$next__4341.invokeStatic (core.clj:64) 
clojure.core.protocols$fn__6755.invokeStatic (protocols.clj:168) 
clojure.core.protocols/fn (protocols.clj:124) 
clojure.core.protocols$fn__6710$G__6705__6719.invoke (protocols.clj:19) 
.... 

上什么可能会导致此任何想法或最佳途径排除故障?我真的很想将Java对象作为Clojure地图进行交互。

+0

您不妨在Google Groups邮件列表中提问这个问题[email protected] –

回答

3

我不会推荐使用clojure.data.java/from-java做任何事情。简单函数可以将任意Java对象转换为合理的Clojure地图,但没有源对象的任何领域知识的想法是一厢情愿的想法。

今天之前我还没有听说过它,但我去看了看源头,并且正如所料,它基本上只是clojure.core/bean的延伸,这是另一个有希望尝试解决不可能问题的延伸。具体来说,它使用javabean introspection来尝试猜测getter和setter表示什么是有意义的字段。然而,像许多Java类不是用来作为bean的,protobuf类包含循环引用,这意味着递归地将它们加入bean是一项无限的任务,最终导致堆栈溢出。

怎么办?我建议只通过Java interop来处理生成的Java protobuf类,或者尝试找到一个好的Clojure protobuf库。不要尝试将Java对象转换为惯用的Clojure数据。

+0

感谢您的支持!我相信你救了我几天的沮丧。我发现似乎是一个有声望的[Clojure protobuf库](https://github.com/ninjudd/clojure-protobuf)。你会不会知道它是否支持proto3?另外,根据您的经验,如果使用Java protobuf类而不是像这个库那样更好? – frank

+0

几年前,我写了一段代码,可以将更多或更少的通用Apache Thrift对象树转换为Clojure数据结构。我使用了一些Thrift生成的对象中可用的元数据,而不是枚举生成的类中的字段。我可以获得每个班级的“业务”字段和类型。因此,我避免了仅存在Thrift需求的额外领域。也许类似的方法也可以应用于Protobuf。 – ez121sl

+0

@ ez121sl是的,这正是Clojure所要做的一个好的protobuf库,它的工作原理是protobuf和节俭一样,有足够的元数据来有意义地描述对象。 – amalloy

相关问题