2013-02-19 5 views
4

Я разрабатываю программу на C++ (Win32, MS Visual Studio 2008), которая создает Java-виртуальную машину через JNI, как указано here. Он работает отлично в течение длительного времени, как с Java 6, так и с Java 7.Вызов Java из C++: как поймать/обнаружить фатальную ошибку JVM?

Сегодня я установил новую версию JRE; в установщике что-то пошло не так, и JRE стал коррумпированным. Я заметил, что моя программа на C++ не запускается и не выдает никаких предупреждающих сообщений. Отладка программы показала, что она успешно работает до вызова JNI_CreateJavaVM; но вызов JNI_CreateJavaVM заставляет программу немедленно завершать работу. Нет возвращаемых значений, сообщений об ошибках, ничего.

Да, я знаю, что мне просто нужно переустановить JRE. Но тем не менее я бы хотел, чтобы моя программа на C++ была подготовлена ​​к такой ситуации. Если он не может создать виртуальную машину Java, он должен показать сообщение «Пожалуйста, переустановите JRE». Но у меня нет возможности показать это сообщение, потому что вся программа завершается.

Есть ли способ обнаружить такие ошибки в JRE или, более широко, в сторонней библиотеке? Я попытался использовать конструкции C++ try/catch, я попытался использовать функцию signal - ничего не помогает; программа исчезает, не вызывая никаких уловов или обработчиков сигналов.

Есть ли способ обнаружить такие аварии JRE? Или: есть ли способ надежно обнаружить сбой или завершение внутри сторонней библиотеки?

+0

В какой среде? Существуют зависимые от ОС/зависимые от компилятора способы (например, __try __except на MS C++) –

+0

Или [SetUnhandledExceptionFilter] (http://msdn.microsoft.com/en-us/library/ms680634%28VS.85%29.aspx) для win32 –

+0

@ dema80, да, это Win32. Спасибо за подсказку, я отредактировал вопрос. –

ответ

1

Если вы используете Linux/Unix: это то, что я обычно начинаю с:

struct sigaction sa; 
sa.sa_handler = bt_sighandler; 
sigemptyset(&sa.sa_mask); 
sa.sa_flags = SA_RESTART; 

sigaction(SIGSEGV, &sa, NULL); 
sigaction(SIGUSR1, &sa, NULL); 

Если вы используете Microsoft C++ на окнах: _ попробовать/ _except обычно будет делать трюк. Это расширение MSVC (вы можете сказать из двойного подчеркивания), которое расширяет стандартный try/catch.

Попробуйте/поймайте уловы C++ исключения, _ try/ _except поймает все остальные необработанные исключения (COM, Win32, ...). Например, он будет улавливать нулевые разыменования, проблемы с доступом к памяти, которые, вероятно, являются причиной вашего сбоя. Читать here

В противном случае, вдовы, попробуйте SetUnhandledExceptionFilter

EDIT: так как подход, использующий SEH, кажется, не в состоянии, вы можете перейти на один уровень вверх и использовать векторную обработку исключений. Согласно this blog post on msdn, VEH регистрируется в процессе, и он проверяется перед SEH.

Если все не удается, не отчаивайтесь :) вы все равно можете превратить свое приложение в пара-отладчик/debugee. Это даст вам полный контроль над событиями, жизнью и смертью дебютного процесса. Обычно это НЕ стоит того, но это дополнительное решение, которое мне пришлось использовать в прошлом. Это также не так сложно, как может показаться; если что-то еще не удастся, сообщите мне, и я выкопаю какой-то старый код.

+0

Что-то странное происходит.try/catch, __try/__ except, signal, SetUnhandledExceptionFilter не справляются с ошибкой. Однако, если я покажу MessageBox перед вызовом JNI_CreateJavaVM, все эти конструкции начинают работать; в частности, сигнал сообщает об ошибке SIGSEGV (нарушение доступа к памяти); то программа сможет продолжить работу. Очевидно, я не могу отображать MessageBox каждый раз. Может быть, отображать невидимое окно? Ugh, черная магия ... –

+0

Umm .. звучит подозрительно, как проблема с потоками .. можете ли вы опубликовать код, показывающий, как вы используете SetUnhandledExceptionFilter? (сигнал в Win32 использует SetUnhandledExceptionFilter внизу, IIRC) –

+0

К сожалению, это не MessageBox. Вместо прямого вызова MessageBox я вызвал мою функцию отчетности об ошибках, которая также выпустила библиотеку, с которой я вызывал CreateJavaVM, поэтому нарушение прав было вызвано неправильным указателем на функцию, а не сбоем Java. Таким образом, на самом деле ничто, похоже, не в состоянии поймать крах. –

Смежные вопросы