Управление памятью JNI с помощью Вызова API

Таким образом, в основном сценарий использования был инициировать запрос LiveData после некоторого события - в данном случае намерение из BroadcastReceiver - поэтому он обновляется. Я хотел поставить новые параметры для запроса, а затем заставить запрос работать.

То, что я не понял, это то, что это в основном против дизайна LiveData. LiveData это данные, на которые вы подписываетесь, клиент, который подписывается на эти данные, не влияет на них, он просто слушает их изменения. Так что проблема здесь с дизайном.

Чтобы получить новый запрос, вам обычно нужны либо новые данные (чтобы ваши наблюдения сработали), либо повторная подписка на LiveData - более сложный и сложный подход, так как вам нужно управлять подписками, чтобы вы не делали не течь. Я решил получить новые данные с помощью вставки, как только я получу намерение. Если кто-то пожелает, я могу опубликовать фиксированный код для этого.

6
задан Chris R 18 October 2008 в 06:56
поделиться

4 ответа

Существует несколько стратегий исправления собственных ресурсов (объекты, дескрипторы файлов, и т.д.)

  1. Вызовите метод JNI во время, завершают (), который освобождает ресурс. Некоторые люди рекомендуют против реализации, завершают, и в основном Вы не можете действительно быть уверены, что Ваш собственный ресурс когда-либо освобождается. Для ресурсов, таких как память это - вероятно, не проблема, но если у Вас есть файл, например, который должен быть сброшен в предсказуемое время, завершить (), вероятно, не хорошую идею.

  2. Вручную вызовите метод очистки. Это полезно, если у Вас есть момент времени, где Вы знаете, что ресурс должен быть очищен. Я использовал этот метод, когда у меня был ресурс, который должен был быть освобожден прежде, чем разгрузить DLL в коде JNI. Чтобы позволить DLL позже быть перезагруженным, я должен был быть уверен, что объект был действительно освобожден прежде, чем попытаться разгрузить DLL. Используя только завершают (), я не гарантировал бы это. Это может быть объединено с (1), чтобы позволить ресурсу быть выделенным, любой во время завершает () или во вручную названном методе очистки. (Вам, вероятно, нужна каноническая карта WeakReferences для отслеживания, какие объекты должны были вызвать их метод очистки.)

  3. Предположительно, PhantomReference может использоваться для решения этой проблемы также, но я не уверен точно, как такое решение работало бы.

На самом деле я должен не согласиться с Вами на документации JNI. Я нахожу спецификацию JNI исключительно ясной по большинству важных проблем, даже если разделы по управлению локальными и глобальными ссылками, возможно, были более разработаны.

5
ответ дан 8 December 2019 в 14:49
поделиться

Спецификация JNI охватывает проблему того, кто "владеет" объектами Java, созданными в методах JNI здесь. Необходимо различать локальные и глобальные ссылки.

Когда JVM заставляет JNI обратиться к собственному коду, она настраивает реестр для отслеживания все объекты, созданные во время вызова. Любой объект, созданный во время собственного вызова (т.е. возвратился из функции интерфейса JNI), добавляется к этому реестру. Ссылки на такие объекты известны как локальные ссылки. Когда собственный метод возвращается к JVM, все локальные ссылки, созданные во время вызова собственного метода, уничтожаются. Если Вы превратите вызовы назад в JVM во время вызова собственного метода, то локальная ссылка все еще будет жива, когда управление возвратится назад к собственному методу. Если JVM, вызванная из собственного кода, превращает другой вызов назад в собственный код, новый реестр локальных ссылок создается, и те же правила применяются.

(На самом деле можно реализовать, Вы - собственный исполняемый файл JVM (т.е. java.exe) использование интерфейса JNI, путем создания JVM (таким образом, получающий JNIEnv * указатель), ища класс, данный на командной строке, и вызывая основное () метод на нем.)

Все ссылки, возвращенные из методов интерфейса JNI, локальны. Это означает, что при нормальных обстоятельствах Вы не должны вручную освобождать ссылочный возврат методами JNI, так как они уничтожаются при возврате к JVM. Иногда Вы все еще хотите уничтожить их "преждевременно", например, когда Вы много локальных ссылок, которые Вы хотите удалить прежде, чем возвратиться к JVM.

Глобальные ссылки создаются (из локальных ссылок) при помощи NewGlobalRef (). Они добавляются к специальному реестру и должны быть освобождены вручную. Глобальные ссылки только используются для объекта Java, на который собственный код должен содержать ссылку через несколько вызовов JNI, например, если у Вас есть инициирующие события собственного кода, которые должны быть распространены назад к Java. В этом случае код JNI должен сохранить ссылку на объект Java, который должен получить событие.

Надежда это разъясняет управление памятью, выходит немного.

10
ответ дан 8 December 2019 в 14:49
поделиться

Ре: "Отдельный, но связанный вопрос"... Вы не должны вручную выпускать jclass, jfieldID и jmethodID при использовании их в "локальном" контексте. Любые ссылки фактического объекта, которые Вы получаете (не jclass, jfieldID, jmethodID) должны быть выпущены с DeleteLocalRef.

1
ответ дан 8 December 2019 в 14:49
поделиться

GC собрал бы Ваш экземпляр, но он автоматически не освободит память "кучи" не-Java, выделенную в собственном коде. У Вас должен быть явный метод в Вашем классе для выпуска c_object экземпляра.

Это - один из случаев, где я рекомендовал бы использовать финализатор, проверяющий, был ли c_object выпущен и выпускает его, регистрируя сообщение, если это не.

Полезная техника состоит в том, чтобы создать экземпляр Throwable в конструкторе класса Java и сохранить его в поле (или просто инициализировать встроенное поле). Если финализатор обнаружит, что класс не был правильно расположен, то он распечатает stacktrace, точно определяя стопку выделения.

Предложение состоит в том, чтобы не делать прямой JNI и пойти с gluegen или Большим глотком (и генерируют код и может быть статически связан).

0
ответ дан 8 December 2019 в 14:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: