18

I'm using sbt 0.13 and have issues using the leveldbjni native library under sbt (even after issue #358 has been resolved). A similar issue has already been reported for which sbt 0.13 should provide a solution but it seems it doesn't. So I'm sharing my observations here.

I'm getting an UnsatisfiedLinkError with the following example application.

  • build.sbt

    name := "example"
    
    version := "0.1"
    
    scalaVersion := "2.10.2"
    
    libraryDependencies += "org.fusesource.leveldbjni" % "leveldbjni-all" % "1.7"
    
  • build.properties

     sbt.version=0.13.0
    
  • Example.scala

    import org.fusesource.leveldbjni.internal._
    
    object Example extends App {
      NativeDB.LIBRARY.load() // loading succeeds 
      new NativeOptions() // UnsatisfiedLinkError under sbt
    }
    

I'm using Oracle JDK 1.7 and OS X 10.8.5. Running the example with run-main Example under sbt gives

[error] (run-main) java.lang.UnsatisfiedLinkError: org.fusesource.leveldbjni.internal.NativeOptions.init()V

whereas running it with

java -cp scala-library.jar:example_2.10-0.1.jar:leveldbjni-all-1.7.jar Example

just works fine. The application even runs successfully when Scala is on the bootclasspath:

java -Xbootclasspath/a:scala-library.jar -cp example_2.10-0.1.jar:leveldbjni-all-1.7.jar Example

Any ideas why there's an UnsatisfiedLinkError only under sbt?

Community
  • 1
  • 1
Martin Krasser
  • 745
  • 5
  • 13
  • 2
    This is just a workaround, but have you tried [forking](http://www.scala-sbt.org/release/docs/Detailed-Topics/Forking.html)? – gourlaysama Oct 17 '13 at 16:18
  • @gourlaysama yes, with forking it actually works but, as you said, it's just a workaround. Thanks anyway. – Martin Krasser Oct 18 '13 at 05:19
  • 1
    I should also add that the forking workaround only works with sbt 0.13, not with earlier versions. – Martin Krasser Oct 18 '13 at 05:40
  • 1
    Sbt is using magic classloaders to try to prevent "leaks" of native loaded libraries, and allow you to re-import the library multiple times. Sbt will actually rename the DLL/SO/jnilib and load it in a special classloader. I'm not positive if this is only a plugin feature, or something for all apps. Where I've seen this in the past is when not using this functionality and having my native library already linked on another classloader. Does this happen on every run, or only after a successful run? – jsuereth Oct 23 '13 at 13:48
  • @jsuereth This happens on every run. – Martin Krasser Oct 24 '13 at 09:59
  • Martin did you manage to solve this issue ? I am working with akka persistence and i am having the same error – integratingweb Nov 29 '13 at 12:50
  • 4
    @integratingweb fork your tests (recommended) or set akka.persistence.journal.leveldb.native=off (works without forking but should be used only for testing) – Martin Krasser Nov 30 '13 at 14:07
  • It may be of some help - https://github.com/eligosource/eventsourced/wiki/Installation#wiki-native. – Jacek Laskowski Feb 09 '14 at 12:59
  • @JacekLaskowski thanks, but I'm the author of this Wiki page :) This page is also linked in the sbt issue #358 linked above. – Martin Krasser Feb 10 '14 at 13:41

1 Answers1

7

Any ideas why there's an UnsatisfiedLinkError only under sbt?

As @juereth commented:

Sbt is using magic classloaders to try to prevent "leaks" of native loaded libraries, and allow you to re-import the library multiple times. Sbt will actually rename the DLL/SO/jnilib and load it in a special classloader. I'm not positive if this is only a plugin feature, or something for all apps.

So this is somewhat expected behavior with the current design of sbt. If forking works, then that's what you have to do.

Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319