У меня довольно простая программа Scala для получения хеш-значения строк, извлеченных из базы данных.Хеш-функция, которую я должен использовать, - cityhash64, созданная Google, которая имеет только реализацию C ++.Поэтому мое решение состоит в том, чтобы создать один C ++ libCityhashNative.so, вызываемый моей программой Scala spark через JNI.Это .so вернет мне хэш-значение строки, в которую я передал.
- Я упаковал libCityhashNative.so в Runnable jar tdw_spark-1.0-all.jar.
- Извлеките его из jarи запишите его во временный путь к серверу.
- Загрузите его по
System.load(tmp.getAbsolutePath())
.
Мой код такой:
package com.tencent.omg.tasks.jni
class CityhashNative {
// --- Native methods
@native def intMethod(n: Int): Int
@native def getCityHash64(strToHash: String, length: Int, ddwSeed: Int): Int
}
object CityhashNative {
val path="/video/libCityhashNative.so"
val prefix = "libCityhashNative"
val suffix = ".so"
//create tmp file on server with file prefix and suffix
val tmp = File.createTempFile(prefix, suffix)
var buff = new Array[Byte](1024)
val len : Int = 0
val out = new FileOutputStream(tmp)
//load libCityhashNative.so from Jar to inputStream
val in = getClass.getResourceAsStream(path)
val reader = new BufferedInputStream(in)
//write libCityhashNative.so to server location tmp via outputStream
while(reader.read(buff)>0){
out.write(buff)
buff = new Array[Byte](1024)
}
System.load(tmp.getAbsolutePath())
val chn = new CityhashNative
val hashValue = chn.getCityHash64("XXXX", 9, 5)
}
Дело в том, что проводнойкогда я запускаю флягу по
spark-submit --master local --class com.tencent.omg.tasks.jni.CityhashNative tdw_spark-1.0-all.jar
, я получаю ошибку ниже:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.tencent.omg.tasks.jni.CityhashNative.getCityHash64(Ljava/lang/String;II)I
at com.tencent.omg.tasks.jni.CityhashNative.getCityHash64(Native Method)
at com.tencent.omg.tasks.jni.CityhashNative$.main(CityhashNative.scala:86)
at com.tencent.omg.tasks.jni.CityhashNative.main(CityhashNative.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:744)
at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:187)
at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:212)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:126)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Но если я бегу по
scala -cp . CityhashNative
, это работает !!!
Так что я немного запутался, когда сделал неправильно, когда сгенерировал банку.или причина в том, что .so не загружен успешно?
Любой совет будет очень признателен.
PS: я уверен, что libCityhashNative.so успешно извлечен из jar и записан на сервервременный путь.