我有一个Fortran代码,我尝试将其包装为Java / Scala代码。我的问题是,即使我将库放在两个调用之间,fortran中变量的状态也会保留:
Fortran代码:
subroutine mySub()
implicit none
DOUBLE PRECISION x
COMMON/myCommon/ x
print*,x
x = 99.99
end subroutine mySub
和Java / Scala代码:
trait FortranLibrary extends Library {
// native symbols
def mysub_()
}
def main(args: Array[String]): Unit = {
var INSTANCE: FortranLibrary = Native.synchronizedLibrary(
Native.load("sub.so", classOf[FortranLibrary])
).asInstanceOf[FortranLibrary]
// call native subroutine
INSTANCE.mysub_()
println("------SECOND CALL-----")
// clean library, reload
INSTANCE = null
System.gc()
// make new instance
INSTANCE = Native.synchronizedLibrary(
Native.load(libpath, classOf[FortranLibrary])
).asInstanceOf[FortranLibrary]
// call native subroutine
INSTANCE.mysub_()
}
打印到控制台:
0.000000000000000E+000
------SECOND CALL-----
99.9899978637695
因此,即使按How to dispose library loaded with JNA中的建议配置了库,在第二个调用中仍然存在先前设置的x = 99.99,如何避免这种情况?
编辑:我正在使用带-init:zero
的intel fortran编译器,因此变量应使用0重新初始化
[在幕后,一旦您加载了NativeLibrary
对象,JNA就会保留对它的引用,除非明确调用dispose()
,否则它不会释放它。
dispose()
方法包含在对象的finalize()
中,该方法将在垃圾回收时被调用,但是,不能始终执行此方法。在发布的代码段中,您将引用设为空,并使用单个System.gc()
调用,这仅是释放对象的建议。在您尝试过的注释中指出的一个更好的选择是自己调用dispose()
或disposeAll()
。
但是,正如[C0]中所指出的那样,需要很小的时间延迟以确保本机库在立即重新加载后不会返回相同的句柄。 my answer to your linked question注意在OSX上至少可以延迟2毫秒,并且在您的评论中,您似乎已经成功在OS上进行了10毫秒的延迟。