JNA сохраняет состояние даже после перезагрузки библиотеки - PullRequest
0 голосов
/ 19 марта 2020

У меня есть код на Фортране, который я пытаюсь обернуть в код Java / Scala. Моя проблема заключается в том, что состояние переменной в Fortran сохраняется, даже если я располагаю библиотеку между двумя вызовами:

Fortran-Code:

  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 все еще присутствует во втором вызове, даже если библиотека расположена, как предложено в Как избавиться от библиотеки, загруженной с помощью JNA , как этого избежать?

РЕДАКТИРОВАТЬ: я использую компилятор Intel Fortran с -init:zero, поэтому переменные должны быть повторно инициализированы с 0

1 Ответ

0 голосов
/ 21 марта 2020

Под капотом JNA хранит ссылку на NativeLibrary объект, как только вы загрузили его, и не освобождает его, если явно не вызван dispose().

Метод dispose() включен в объект finalize(), который будет вызываться при сборке мусора, однако на него нельзя полагаться, чтобы он всегда выполнялся. В размещенном вами фрагменте кода вы обнуляете ссылку и используете один вызов System.gc(), который является лишь предложением для освобождения объекта. Лучший вариант, который вы указали в комментариях, которые вы пробовали, это позвонить dispose() или disposeAll() самим.

Однако, как также отмечалось в моем ответе на вашу ссылку вопрос , требуется небольшая задержка, чтобы гарантировать, что нативная библиотека не возвращает тот же дескриптор, если она сразу же перезагружается Исходный код JNA отмечает, что как минимум задержка в 2 мс работает в OSX, и в ваших комментариях кажется, что вы добились успеха в своей ОС с задержкой в ​​10 мс.

...