我正在使用org.zeromq java库用于ZMQ,它在生产部署和我在IntelliJ内部运行测试时运行良好,但是如果我尝试在同一台机器上通过sbt从命令行运行相同的测试它失败了:
java.lang.AbstractMethodError: com.sun.jna.Structure.getFieldOrder()Ljava/util/List;
at com.sun.jna.Structure.fieldOrder(Structure.java:868) ~[jna-4.0.0.jar:4.0.0 (b2)]
... (8 lines omitted)
at org.zeromq.zmq_msg_t.<init>(zmq_msg_t.java:21) ~[zeromq-scala-binding_2.10-0.0.7.jar:0.0.7]
at org.zeromq.ZMQ$Socket.newZmqMessage(ZMQ.java:453) ~[zeromq-scala-binding_2.10-0.0.7.jar:0.0.7]
at org.zeromq.ZMQ$Socket.send(ZMQ.java:368) ~[zeromq-scala-binding_2.10-0.0.7.jar:0.0.7]
测试只是这样:
class ZeroMQSpec extends FlatSpec with Matchers with LazyLogging {
"zeroMQ" should "be able to just send something" in {
val context = ZMQ.context(1)
val socket = context.socket(ZMQ.PAIR)
socket.bind("inproc://zmqtest")
logger.debug("start polling")
try {
socket.send(Array[Byte](1, 2), 0)
logger.debug("done polling")
} catch {
case e: Throwable => logger.error("ZMQ failed", e)
}
}
send
只是一个例子。同样适用于recv
或poll
。
由于同一测试在同一台机器上的IntelliJ下运行,而ZMQ也适用于生产代码,因此它似乎与安装的本机ZMQ无关,而是JVM如何绑定它。不幸的是,我不知道如何进一步解决这个问题。
更新
在@cdshines问题的提示下,我查看了JNA在类路径中需要的工作和this,我需要platform.jar和jna.jar。在IntelliJ中,他们都来自我的常春藤缓存:
file:/Users/arne/.ivy2/cache/net.java.dev.jna/jna/jars/jna-3.0.9.jar
file:/Users/arne/.ivy2/cache/net.java.dev.jna/jna/jars/jna-4.0.0.jar
file:/Users/arne/.ivy2/cache/net.java.dev.jna/platform/jars/platform-3.4.0.jar
我认为SBT也应该解决。既然不是,有没有办法强迫SBT这样做?
更新2
加
"net.java.dev.jna" % "jna" % "4.0.0" % "test",
"net.java.dev.jna" % "jna-platform" % "4.0.0" % "test",
到我的依赖项。行为没有变化
答案 0 :(得分:1)
您的zeromq-scala-binding
版本取决于JNA版本3.0.9
,但您运行的是JNA版本4.0.0
,它不是二进制兼容的。
您需要将JNA 4排除在其他依赖项之外。您可以使用sbt-dependency-graph找出哪一个。
通常情况下,我害怕通过强制使用JNA 3来打破其他依赖关系,但你说它在生产中有效,所以你应该没事。