即使重新加载库,JNA 也会保持状态
JNA keeps state even if library is reloaded
我有一个 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 仍然存在于第二次调用中,即使库已按照 中的建议进行处理,如何避免这种情况?
编辑:我正在使用带有 -init:zero
的英特尔 Fortran 编译器,因此应该使用 0
重新初始化变量
在后台,JNA 会在您加载后保留对 NativeLibrary
对象的引用,并且不会释放它,除非显式调用 dispose()
。
dispose()
方法包含在对象的 finalize()
中,该方法将在垃圾回收时调用,但是,不能依赖它始终执行。在您发布的代码片段中,您使引用为空并使用单个 System.gc()
调用,这只是释放对象的建议。更好的选择是您自己在评论中指出 dispose()
或 disposeAll()
。
但是,正如 , a small time delay is needed to ensure the native library doesn't return the same handle if it's immediately reloaded. JNA source code 中所述,至少 2 毫秒的延迟适用于 OSX,并且在您的评论中,您的 OS 似乎已经成功延迟 10 毫秒。
我有一个 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 仍然存在于第二次调用中,即使库已按照
编辑:我正在使用带有 -init:zero
的英特尔 Fortran 编译器,因此应该使用 0
在后台,JNA 会在您加载后保留对 NativeLibrary
对象的引用,并且不会释放它,除非显式调用 dispose()
。
dispose()
方法包含在对象的 finalize()
中,该方法将在垃圾回收时调用,但是,不能依赖它始终执行。在您发布的代码片段中,您使引用为空并使用单个 System.gc()
调用,这只是释放对象的建议。更好的选择是您自己在评论中指出 dispose()
或 disposeAll()
。
但是,正如