Java通过jni方式调用gdal踩过的坑

目录

  • 背景
  • 编译gdaljni
    • ant
    • proj & geos
    • gdaljni
  • 配置eclipse环境
  • 部署运行
    • java.lang.UnsatisfiedLinkError: no gdaljni in java.library.path
    • java.lang.UnsatisfiedLinkError: /HDFS/CC/Bin/libgdaljni.so: libproj.so.13: cannot open shared object file: No such file or directory
  • 后记

背景

近期项目需要添加一个使用到gdal的模块,领导交给我来完成,说用Java和C++都可以。什么?C++?!我可不想去处理指针[手动捂脸],果断选择Java!其实也是为了能与现有系统更好的兼容,并且以后也更容易迁移,行了编不下去了。。。

但是奶衣污的我发现gdal并不原生支持Java语言,需要利用jni方式来间接使用。jni的具体定义和内涵我没有细查,应该是Java里面调用C/C++编译的so库API的一种方式。好读书,不求甚解,暂时不懂的可以留着以后需要时再学习,当前不影响正常使用即可。时间宝贵,阿弥陀佛。

编译gdaljni

系统环境为Linux,Java和gdal均已安装好,在此就不赘述了。额外需要的插件包括ant、proj和geos。proj和geos是gdal实现投影与地理变换需要的第三方库(大概是吧,存疑,哈哈),ant是编译gdaljni所需要的一个编译工具。

ant

ant的安装炒鸡简单,去官网下载tar.gz包,解压后export其bin目录到PATH环境变量即可,想要永久生效就把这个export语句写到~/.bashrc里面去。总而言之,就是敲ant的时候系统得知道运行那个bin文件夹下的ant二进制可执行文件,而不是告诉咱command not found...

proj & geos

也很简单,去官网下载,解压,依次执行./configure; make; make install即可,说白了就是分别编译了一个静态库.a和一个动态库.so。均默认安装到/usr/local/lib下,这个目录一般也在LD_LIBRARY_PATH中,不用另外配置,完美。

gdaljni

前戏整完了,接下来正式进入。。。我怎么感觉屏幕变黄了。这个的编译也好说,在gdal的安装目录下,找到swig目录,再进入java目录,好了开整。首先配置java.opt文件,敲入以下内容:

JAVA_HOME=/usr/jdk64/jdk1.8.0_121 #这里写你自己实际的jvm路径
JAVADOC=$(JAVA_HOME)/bin/javadoc
JAVAC=$(JAVA_HOME)/bin/javac
JAVA=$(JAVA_HOME)/bin/java
JAR=$(JAVA_HOME)/bin/jar
JAVA_INCLUDE=-I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux

最后make一发就打完收工了。make完后发现编译生成了gdaljni、gdalconstjni、osrjni、ogrjni、gnmjni等库,以及一个gdal.java文件。

配置eclipse环境

本人使用eclipse开发,据说现在比较流行IDEA,有机会玩一玩。这里简单来说分两步,第一步,导入上一步生成的gdal.java类文件,项目属性-> Java Build Path-> Libraries-> Add External Jars…-> 选取该文件,完事。这样一来import org.gdal.*就不会报错了。有了上层的API接口,没有下层的实现可不行,所以第二部就是让项目找得到上一步生成的那些***jni.so文件,具体操作是项目属性-> Java Build Path-> Libraries-> JRE System Library-> Native Library Location,选择包含这些***jni.so的目录即可。

部署运行

世界上本来并没有坑,走的人多了,就有了坑。 ——沃兹基硕德
运行的时候是在集群中,环境变了难免会有不少坑。

java.lang.UnsatisfiedLinkError: no gdaljni in java.library.path

这是由于那些***jni.so 文件没有被找到导致的,解决方法第一种就是将这些库放到当前执行程序的目录,呵呵治标不治本,那么第二种来了,就是java -jar 运行的时候,加上这么一项-Djava.library.path=/The/Path/To/The/SoFiles/,即java -Djava.library.path=/The/Path/To/The/SoFiles/ -jar RunableJarFile [args]

java.lang.UnsatisfiedLinkError: /HDFS/CC/Bin/libgdaljni.so: libproj.so.13: cannot open shared object file: No such file or directory

***jni.so 找到了但是人家还依赖别的库了,好人做到底送佛送到西,得让人家功德圆满才行。好了,先ldd libgdaljni.so看看都有哪些库not found, 缺啥补啥就行了。不想大量拷贝文件,就export LD_LIBRARY_PATH,把该包含的包含进来就行。

后记

至此暂时告一段落,后面还有个问题就是gdal相关的了,java的API貌似不太健全,AutoCreateWarpedVRT虽然很方便,但是不能指定输出分辨率,有点不爽。去gdal的GitHub库大概看了一下,也没找到解决方案。人家说“The GDALSuggestedWarpOutput() function is used to determine the bounds and resolution of the output virtual file which should be large enough to include all the input image”,我不想你用GDALSuggestedWarpOutput,我想自己指定啊哭。没办法,可以考虑去改它的源码(估计挺麻烦,望而却步),也可以用C++写一个小程序实现这个功能,再用java来调用。害,绕来绕去还是回到了C++,苍天饶过谁。。。

第一篇博客,耗时1.5小时,风格很皮,但我喜欢哈哈。自己表达能力欠佳,要多输出,多写,加油啊~

你可能感兴趣的:(java,java,gdal)