Обновленная DLL заставляет JNI выдавать «Exception c0000005» - PullRequest
2 голосов
/ 04 августа 2010

Вот моя проблема.

У меня есть третья часть DLL (для которой у меня нет источника), с которой я должен использовать JNI для общения.Люди, которые поставляют эту DLL, не являются Java-домом.Я обнаружил ошибку в их DLL, поэтому написал несколько C ++, которые использовали их DLL, выявили ошибку и отправили их для исправления.Я, наконец, получил от них обновленную DLL, запустил свой код C ++ (который работал нормально) и обнаружил, что ошибка действительно была исправлена.

Однако теперь, когда я использую эту новую DLL внутри моего кода JNI, я получаюследующее исключение:

Exception c0000005, at 1EEE3416
Access violation: attempting to read memory at address 00000004
Native function stack data: 0,3f49c0,20201,801c6,65637845,6f697470,3063206e,30303030
com.jniwrapper.FunctionExecutionException: c0000005
 at com.jniwrapper.Function.invokeCFunc(Native Method)
 at com.jniwrapper.FunctionCall.a(SourceFile:127)
 at com.jniwrapper.FunctionCall.call(SourceFile:35)
 at com.jniwrapper.Function.invoke(SourceFile:188)
 at com.tme.techdoc3.diagnostic.api.denso.DensoApiInvoker.invoke(DensoApiInvoker.java:78)
 at com.tme.techdoc3.diagnostic.api.denso.NewDensoApi.invoke(NewDensoApi.java:106)
 at com.tme.techdoc3.diagnostic.api.denso.NewDensoApi.connect(NewDensoApi.java:46)
 at ConsoleApiRunner.main(ConsoleApiRunner.java:59)

Я на самом деле использую JNIWrapper для предоставления своего кода JNI и, таким образом, чтобы исключить их продукт как вызывающий проблему, вместо этого я написал свой собственный код JNI;но я все еще получаю эту же ошибку.Это убеждает меня в том, что проблема в сторонней DLL.

Я получаю это исключение из самой первой функции, которую я вызываю в DLL (кстати, в этой функции не было ошибки ...).

Место, откуда мы получаем DLL, прямо заявило, что они не будут поддерживать ее использование в среде JNI, даже если они не будут отправлять мне какие-либо заметки о выпуске или список изменений междуфиксированные и нефиксированные библиотеки DLL.

Политически я ничего не могу с этим поделать.Практически, я ограничен этим поставщиком для DLL.

Может кто-нибудь придумать причину, по которой эта DLL будет работать при вызове из C ++, а не при вызове из JNI?Я играл с размером стека JNI (-Xss) и некоторыми другими параметрами JVM, но я либо еще не выбрал правильные настройки, либо смотрю не на ту вещь.

Любые идеис благодарностью.

Большое спасибо.

РЕДАКТИРОВАТЬ: Добавление в мой собственный код JNI, чтобы увидеть, если кто-то может обнаружить ошибку.

РЕДАКТИРОВАТЬ 2: Исправленный код copy-n-paste error.

Когда я использую свой собственный код JNI, вот реализация файла .cpp, который я использую;

#include "stdafx.h"
#include "windows.h"
#include "MyJniApi.h"
#include "ThirdParty.h"
#pragma comment(lib, "ThirdParty.lib");

ThirdPartyThing* thirdParty;

JNIEXPORT jlong JNICALL Java_com_mycompany_jni_MyJniApi_connect(JNIEnv *, jobject) {
    long connId = 0L;
    thirdParty = new ThirdPartyThing();
    long retval = thirdParty->GetConnection(&connId);
    if(0 == retval) {
        return connId;
    } else {
        return retval;
    }   
}

Как вы можете видеть, это довольно просто, и яя не вижу там места, когда я перепутал мои указатели и т.д.(Отказ от ответственности: это в значительной степени сумма моих навыков C ++!)

Ответы [ 3 ]

0 голосов
/ 17 августа 2010

Мое предложение основано на этом предположении - если вы можете заставить его работать в C ++, то вы должны иметь возможность заставить его работать в JNI.

Прошло много времени с тех пор, как я использовал JNI, но такие проблемы былиобычно вызваны простейшими вещами.

Я бы очень тщательно проверил, что вы используете все обновленные файлы заголовков .h / .lib и т. Д., Поставляемые с новой DLL.Восстановите ваш объект определения JNI после проверки, что вы указываете на все новые файлы, правильные пути (включая ваш текущий JRE).Выполните поиск по всей файловой системе и удалите все предыдущие версии старой библиотеки DLL и ее зависимостей / headers / libs / .obj и т. Д. Один устаревший файл может быть причиной проблемы.

Однажды я потратил три дня на проблему,какое-то приложение помещает копию основной библиотеки Windows в свою собственную программную директорию (а затем добавляется в PATH), что приводит к хаосу при попытке загрузить правильную.

Кстати: есть ли у DLL странная аутентификация /лицензионное поведение?или нужно загрузить другие зависимости, которые он не может разрешить?

0 голосов
/ 17 августа 2010

Хорошо, это было решено (а не решено).

Недавно я понял, что по пути ввел красную сельдь. Когда я написал свой собственный код JNI (чтобы исключить проблемы с продуктом JNIWrapper) и объявил, что исключение все еще выбрасывается, я, должно быть, застрял в одном из кругов DLL Hell. Когда я впервые представил собственный код JNI, было сгенерировано исключение, однако в последующие дни повторный запуск моего собственного кода JNI не вызывал исключение. Поэтому я предполагаю, что у меня где-то лежала старая DLL, что приводило к ошибочным результатам.

Итак, новая информация: Исключение выдается при использовании с JNIWrapper, но не с внутренним кодом JNI.

Так что теперь я копнул глубже в JNIWrapper. В одном из их сообщений на форуме поддержки где-то говорится, что оболочка JNI не предназначена для библиотек DLL C ++, а именно поддерживает только подмножество функций языка C ++. Виртуальные методы являются особым недостатком. Поскольку моя сторонняя DLL-библиотека является C ++, я полагаю, что в предыдущей версии они использовали не поддерживающие JNIWrapper языковые функции, но теперь они есть. Для меня это означает, что я больше не могу использовать инструмент JNIWrapper.

Вместо этого я использую Swig для генерации всего JNI-кода, который мне нужен. Swig выглядит так, как будто это лучший выбор, чем JNIWrapper, так как полученный Java-код намного чище.

Спасибо всем, кто дал предложения. Я думаю, что по крайней мере один аспект каждого ответа был правильным и полезным.

0 голосов
/ 04 августа 2010

c0000005 указывает на «нарушение доступа», это обычно означает, что использовался указатель, который содержит недопустимый адрес памяти.Это может быть просто неверное значение указателя, например, неинициализированное или может указывать на то, что объект был уничтожен.

Я бы посмотрел на две вещи:

  1. Передаваемые вами аргументыв частности любые типы.Я не использовал JNI напрямую, но я думаю, что переменная может быть соединена с C ++ по-другому, если она доступна только для чтения, а не если она может быть записана в.Убедитесь, что любые передаваемые вами буферы выделены, если API-интерфейс DLL ожидает, что они уже выделены.

  2. Время жизни объектов, для которых вы вызываете методы или передаете в качестве аргументов.Убедитесь, что объекты Java, с которыми вы работаете, не собираются во время вызова C ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...