即使重新加载库,JNA也会保持状态

问题描述 投票:0回答:1

我有一个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重新初始化

fortran jna
1个回答
0
投票

[在幕后,一旦您加载了NativeLibrary对象,JNA就会保留对它的引用,除非明确调用dispose(),否则它不会释放它。

dispose()方法包含在对象的finalize()中,该方法将在垃圾回收时被调用,但是,不能始终执行此方法。在发布的代码段中,您将引用设为空,并使用单个System.gc()调用,这仅是释放对象的建议。在您尝试过的注释中指出的一个更好的选择是自己调用dispose()disposeAll()

但是,正如[C​​0]中所指出的那样,需要很小的时间延迟以确保本机库在立即重新加载后不会返回相同的句柄。 my answer to your linked question注意在OSX上至少可以延迟2毫秒,并且在您的评论中,您似乎已经成功在OS上进行了10毫秒的延迟。

© www.soinside.com 2019 - 2024. All rights reserved.