Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala SBT and JNI library

I am writing a simple app in Scala that uses a leveldb database through the leveldbjni library. My build.sbt file looks like this:

name := "Whatever"

version := "1.0"

scalaVersion := "2.10.2"

libraryDependencies ++= Seq(
    "org.iq80.leveldb" % "leveldb-api" % "0.6",
    "org.fusesource.leveldbjni" % "leveldbjni-all" % "1.7"
)

An Object is then responsible for creating a database. Unfortunately if I run the program I get back a java.lang.UnsatisfiedLinkError, raised by the hawtjni library that leveldbjni exploits under the hood.

The error can be triggered easily also from the scala console:

scala> import java.io.File
scala> import org.iq80.leveldb._
scala> import org.fusesource.leveldbjni.JniDBFactory._
scala> factory.open(new File("test"), new Options().createIfMissing(true))

java.lang.UnsatisfiedLinkError: org.fusesource.leveldbjni.internal.NativeOptions.init()V
    at org.fusesource.leveldbjni.internal.NativeOptions.init(Native Method)
    at org.fusesource.leveldbjni.internal.NativeOptions.<clinit>(NativeOptions.java:54)
    at org.fusesource.leveldbjni.JniDBFactory$OptionsResourceHolder.init(JniDBFactory.java:98)
    at org.fusesource.leveldbjni.JniDBFactory.open(JniDBFactory.java:167)
    at .<init>(<console>:15)
...
scala> System getProperty "java.io.tmpdir"
res2: String = /var/folders/1l/wj6yg_wd15sg_gcql001wchm0000gn/T/

I can't understand what is going on since the library is getting correctly extracted from the jar file but it is not getting loaded for some reasons.

$ file /var/folders/1l/wj6yg_wd15sg_gcql001wchm0000gn/T/lib*
/var/folders/1l/wj6yg_wd15sg_gcql001wchm0000gn/T/libleveldbjni-1.7.jnilib:    Mach-O universal binary with 2 architectures
/var/folders/1l/wj6yg_wd15sg_gcql001wchm0000gn/T/libleveldbjni-1.7.jnilib (for architecture x86_64):    Mach-O 64-bit dynamically linked shared library x86_64
/var/folders/1l/wj6yg_wd15sg_gcql001wchm0000gn/T/libleveldbjni-1.7.jnilib (for architecture i386):  Mach-O dynamically linked shared library i386

I think the problem is probably related to the classloader that sbt employs but I am not sure since I am relatively new to scala.

UPDATE

Still didn't find what or who is the culprit. Anyway the library is actually found and correctly loaded, since I can execute the following commands:

scalac> import org.fusesource.leveldbjni.internal.NativeDB
scalac> NativeDB.LIBRARY.load()

The error is somehow due to the init() function that according to the hawtjni documentation is responsible for setting all the static fields annotated as constant fields with the constant value. The exception can still be triggered by typing:

scalac> import org.fusesource.leveldbjni.internal.NativeOptions
scalac> new NativeOptions()
java.lang.UnsatisfiedLinkError: org.fusesource.leveldbjni.internal.NativeOptions.init()V
    at org.fusesource.leveldbjni.internal.NativeOptions.init(Native Method)
    at org.fusesource.leveldbjni.internal.NativeOptions.<clinit>(NativeOptions.java:54)
    at .<init>(<console>:9)
like image 466
nopper Avatar asked Jul 19 '13 16:07

nopper


Video Answer


1 Answers

Apparently this is a known problem as documented in this sbt issue page. I have implemented, according to the eventsourced documentation, a custom run-nobootcp command that executes the code without adding the Scala library to the boot classpath.

This should solve the problem.

like image 70
nopper Avatar answered Sep 20 '22 14:09

nopper