即使重新加载库,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 毫秒。