fortran - 即使重新加载库,JNA 也会保持状态
问题描述
我有一个 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
因此,先前设置的 x=99.99 仍然存在于第二次调用中,即使按照How to dispose library loaded with JNA中的建议处理了库,如何避免这种情况?
编辑:我使用 intel fortran 编译器-init:zero
,所以变量应该用 0 重新初始化
解决方案
NativeLibrary
在后台,一旦你加载了一个对象,JNA 就会保留一个对它的引用,并且除非dispose()
被显式调用,否则它不会释放它。
该dispose()
方法包含在finalize()
将在垃圾收集时调用的对象中,但是不能依赖此方法始终执行。在您发布的代码片段中,您将引用设为空并使用单个System.gc()
调用,这只是释放对象的建议。您在尝试过的评论中指出,一个更好的选择是打电话dispose()
或disposeAll()
自己打电话。
但是,正如我在对您的链接问题的回答中所指出的那样,需要一点时间延迟来确保本机库在立即重新加载时不会返回相同的句柄。 JNA 源代码指出在 OSX 上至少有 2 毫秒的延迟,在您的评论中,您似乎在 10 毫秒延迟的情况下在您的操作系统上取得了成功。
推荐阅读
- android - 带有圆角的 ImageView,看起来像三星图标(松鼠形状)
- vb.net - VB.NET 在每个循环的语句上出现错误
- linux - 删除 0 大小文件的最快方法
- python - For Loop - TypeError:必须是 str,而不是 int
- session-cookies - jquery,从前端删除cookies
- connection - 与主机 localhost 端口 1433 的 TCP/IP 连接失败。错误:“连接超时。”
- reactjs - Typescript React延迟加载路由中的组件
- bash - 管道输入到 bash 脚本(翻译文本)
- apache-kafka - 具有自定义对象数据类型的 Kafka 流聚合
- postgresql - 有没有办法使用 massjs 并使用动态变量作为表名来创建表和选择表?