Методы отладки JNI C ++? - PullRequest
       0

Методы отладки JNI C ++?

4 голосов
/ 26 октября 2010

У меня есть приложение Linux C ++, которое создает JVM и делает вызовы JNI. Я новичок в JNI, и до сих пор я нашел единственный эффективный способ отладки своего приложения во время разработки - методом проб и ошибок. Какие методы можно использовать для отладки печально известной «Java Runtime Environment обнаружила фатальную ошибку» Сбои виртуальной машины Java? Как я узнаю, что проблема в моем коде или в подлинной ошибке JVM?

В общем, очевидная вещь, которую я знаю до сих пор:

  • В коде всегда проверяйте значения jobject, class и jmethodID, возвращаемые из вызовов JNI для значений NULL, прежде чем продолжить.
  • Вызовите env-> ExceptionCheck (), где это необходимо, чтобы убедиться, что нет ожидающих исключений.

В настоящее время я застрял в проблеме, когда трассировка стека в файле отчета об ошибках менее чем полезна:

# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00002b137a99db59, pid=19977, tid=47362673452544
#
# JRE version: 6.0_20-b02
# Java VM: Java HotSpot(TM) 64-Bit Server VM (16.3-b01 mixed mode linux-amd64 )
# Problematic frame:
# V  [libjvm.so+0x40fb59]
  ... <snip> ...
Stack: [0x00007fff1964f000,0x00007fff1974f000],  sp=0x00007fff1974e050,  free space=3fc0000000000000018k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x40fb59]
V  [libjvm.so+0x3ecbe1]
C  [libDataFabric.so+0x1bb5b]  _Jv_JNIEnv::CallObjectMethod(__jobject*, _jmethodID*, ...)+0xe3
etc. ...

Хорошо, я знаю, что он умирает в env-> CallObjectMethod (). Я проверил все параметры этого в GDB, прежде чем он погрузится в код JVM, но я не вижу никаких явных NULL или странных значений. И, конечно, все классы JNI, такие как jobject, бесполезно непрозрачны, поэтому я не могу видеть, указывают ли их указатели на поддельные или реальные данные.

Какие-нибудь советы / предложения / идеи для такого рода проблемы?

Ответы [ 2 ]

5 голосов
/ 26 октября 2010

Хорошо, вот как я подошел к проблеме, о которой упоминал выше.Несколько утомительно, но, при условии достаточного количества времени и усилий, это в конечном итоге окупилось.

  1. Не думайте, что env-> CallMethod (jobj, meth_id, ...) передаются правильные значения.Если это именно то место, где происходит сбой, высока вероятность того, что возникла какая-то труднодоступная, но фундаментальная проблема, например, что передаваемый methodId не соответствует объекту задания, передаваемому в CallObjectMethod (...).Я написал простой вспомогательный метод std::string getClassInfo(JNIEnv* env, jclass aJavaClass), который получает MethodID для «toString» в классе, вызывает этот метод и возвращает результат в виде std :: string.Это говорит мне о том, что объект был тем, о чем я думал, или нет.
  2. Либерально распределите выходные данные отладки между вашими вызовами JNI.В частности, вывод имен классов (например, с помощью вышеуказанного метода) поможет вам выяснить, являются ли объекты погоды тем, кем вы их считаете.
  3. Убедитесь, что вы проверяете нулевые methodID и вызываете env-> ExceptionCheck () послекаждый CallMethod (...).Проверка на нулевое значение после CallMethod (...) не поможет, потому что JNI не может знать, является ли null допустимым типом возврата.
  4. Не думайте, что JNI потерпит крах при первых признакахбеда.Я фактически передавал неправильный тип объекта через несколько вызовов JNI, прежде чем он действительно потерпел крах.См. № 3, чтобы убедиться, что вы поймете проблему рано.
2 голосов
/ 01 ноября 2016

Помните, что в Linux JVM сама использует сигналы SEGV, чтобы указать, что сборщик мусора должен работать. Я использую "обрабатывать SIGSEGV pass noprint nostop" в gdb, чтобы позволить JVM разобраться с этими вещами.

...