Компания, в которой я работаю, недавно перешла на Java 21 с Java 8, что также обновило версию JNI, которая используется для совместимости с C++. Все функции (написанные на C++), вызываемые через JNI, нормально работают на Java 8, но
функция CallStaticObjectMethod выдает исключение Access Violation и вызывает сбой.
Это используется для вызова статического метода на стороне Java.
Функция, вызывающая CallStaticObjectMethod, выглядит следующим образом:
jobject Bindings::ToSystemArchObj(JNIEnv* env, const std::string& arch)
{
if (env == nullptr || arch == ARCH_UNSUPPORTED)
{
return nullptr;
}
jobject jstr = env->NewStringUTF(arch.c_str()); // I have tried converting the type of jstr from jobject to jstring
processArchObj = env->CallStaticObjectMethod(JniProcessInfoDTO::SystemArchClass, JniProcessInfoDTO::ofMethodId, jstr); // THIS LINE IS THROWING access violation and causing crash
return processArchObj;
}
Аргументы JniProcessInfoDTO::SystemArchClass и JniProcessInfoDTO::ofMethodId для этой функции инициализируются в отдельной функции, которая приведена ниже:
void JniProcessInfoDTO::initClass(JNIEnv* env)
{
jclass const localProcessInfoDTO = env->FindClass(JavaTypes::ProcessInfoDTO.c_str());
ProcessInfoDTORef = reinterpret_cast(env->NewGlobalRef(localProcessInfoDTO));
initFieldIDs(env);
// std::string const SystemArch = "Lcom/company/mfw/model/dto/SystemArch;";
SystemArchClass = env->FindClass(JavaTypes::SystemArch.c_str());
// (Ljava/lang/String;)Lcom/company/mfw/model/dto/SystemArch;
const std::string ofSign = "(" + JavaTypes::String + ")" + JavaTypes::SystemArch; //// std::string const String = "java/lang/String;";
ofMethodId = env->GetStaticMethodID(SystemArchClass, "of", ofSign.c_str());
}
Статическая функция do на стороне Java, которую предполагается вызывать, выглядит следующим образом:
package com.company.mfw.model.dto;
public enum SystemArch {
X86, X86_64, UNSUPPORTED;
public static SystemArch of(String arch) {
try {
return SystemArch.valueOf(arch);
} catch (Exception ignored) {
return UNSUPPORTED;
}
}
}
JNI загружается и выгружается следующим образом:
extern "C"
{
// cppcheck-suppress unusedFunction
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*)
{
// This is an entry point for initialization of Java classes.
// All required Java classes must exist and must be initialized here.
// JNI_OnLoad must not be wrapped with Safe Environment.
// JVM should be crashed in case of exceptions here.
JniGlobals::JVMConnector::InitJavaVM(vm);
JavaVMAttachArgs args;
args.version = JNI_VERSION_21;
args.name = nullptr;
args.group = nullptr;
JNIEnv* env = nullptr;
vm->AttachCurrentThread((void**)&env, &args);
JniContext::Current().JniEnv = env;
JniGlobals::unmaskFPSR();
GdiplusStartup(&JniGlobals::gdiplusToken, &JniGlobals::gdiplusStartupInput, nullptr);
Bindings::JniComponentDTO::initClass(env);
Bindings::JniWindowDTO::initClass(env);
Bindings::JniPointDTO::initClass(env);
Bindings::JniDimensionDTO::initClass(env);
Bindings::JniRectangleDTO::initClass(env);
Bindings::JniProcessInfoDTO::initClass(env);
Bindings::JniProcessStartupInfoDTO::initClass(env);
Bindings::JniProcessEndInfoDTO::initClass(env);
Bindings::JniKeyDTO::initClass(env);
Bindings::JniNativeMouseEvent::initClass(env);
Bindings::JniNativeKeyEvent::initClass(env);
Bindings::JniHooksSettings::initClass(env);
Bindings::WinSessionDTO::initClass(env);
JniGlobals::TimeManager::GetInstance().InitJavaHandlers(env);
JniGlobals::JavaObjectFactory::JavaObjectFactoryClass = env->FindClass("com/company/mfw/bridge/internal/JavaObjectsFactory");
JniGlobals::JavaObjectFactory::NewStringMethodID
= env->GetStaticMethodID(JniGlobals::JavaObjectFactory::JavaObjectFactoryClass, "newString", "([B)Ljava/lang/String;");
Log::GetInstance().Init();
LOG_TRACE(L"BEGIN");
auto osInfo = JniGlobals::WindowsSystemInfo::GetInstance().ReadOsInfo();
std::string csd(osInfo.szCSDVersion);
LOG_INFO(L"System info. Version: {}.{}, Build: {}, Platform ID: {}, CSD Version: {}", (int)osInfo.dwMajorVersion,
(int)osInfo.dwMinorVersion, (int)osInfo.dwBuildNumber, (int)osInfo.dwPlatformId,
csd.length() > 0 ? StringsConverter::StringToWstring(csd) : L"");
return JNI_VERSION_21;
}
// cppcheck-suppress unusedFunction
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM*, void*)
{
LOG_TRACE(L"BEGIN");
Gdiplus::GdiplusShutdown(JniGlobals::gdiplusToken);
JNIEnv* env = JniContext::Current().JniEnv;
Bindings::JniComponentDTO::releaseClass(env);
Bindings::JniWindowDTO::releaseClass(env);
Bindings::JniPointDTO::releaseClass(env);
Bindings::JniDimensionDTO::releaseClass(env);
Bindings::JniRectangleDTO::releaseClass(env);
Bindings::JniProcessInfoDTO::releaseClass(env);
Bindings::JniProcessStartupInfoDTO::releaseClass(env);
Bindings::JniProcessEndInfoDTO::releaseClass(env);
Bindings::JniKeyDTO::releaseClass(env);
Bindings::JniNativeMouseEvent::releaseClass(env);
Bindings::JniNativeKeyEvent::releaseClass(env);
Bindings::JniHooksSettings::releaseClass(env);
Bindings::WinSessionDTO::releaseClass(env);
}
} // extern "C"
Документация JNI не содержит никакой информации об этой функции. Может ли кто-нибудь мне здесь помочь?
ОБНОВЛЕНИЕ 1: Все остальные методы JNI работают нормально, только этот вызывает сбой
ОБНОВЛЕНИЕ 2 Все эти функции вызываются для преобразования типа объекта C++ в тип Java. Метод Bindings::ToSystemArchObj вызывается методом, который выполняет это преобразование типа здесь:
/**
* Converts a ProcessInfoPtr to a Java ProcessInfoDTO object.
*
* @param env The JNI environment pointer.
* @param pi The ProcessInfoPtr object.
* @return The corresponding Java ProcessInfoDTO object or nullptr if the environment or ProcessInfoPtr is null.
*/
jobject Bindings::ToJavaType(JNIEnv* env, ProcessInfoPtr pi)
{
if (env == nullptr || pi == nullptr)
{
return nullptr; // Return nullptr if environment or ProcessInfoPtr is null
}
jobject joProcessInfoDTO = env->AllocObject(JniProcessInfoDTO::ProcessInfoDTORef); // Allocate a new ProcessInfoDTO object
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processPidFieldId, pi->pid); // Set process PID field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processParentPidFieldId, pi->parentPid); // Set process parent PID field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processChildProcessFieldId, ToJavaType(env, pi->childProcesses)); // Set child processes field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processCommandLineFieldId, ToJavaType(env, pi->commandLine)); // Set command line field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processNameFieldId, ToJavaType(env, pi->name)); // Set process name field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processOwnerFieldId, ToJavaType(env, pi->owner)); // Set process owner field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processResidentBytesFieldId, pi->residentBytes); // Set resident bytes field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processTotalBytesFieldId, pi->totalBytes); // Set total bytes field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processSystemMillsFieldId, pi->systemMillis); // Set system milliseconds field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processUserMillsFieldId, pi->userMillis); // Set user milliseconds field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processArchFieldId, ToSystemArchObj(env, pi->arch)); // Set process architecture field
return joProcessInfoDTO; // Return the ProcessInfoDTO object
}
Приведенная выше функция пытается преобразовать ProcessInfo в объект Java ProcessInfoDTO. Тип ProcessInfo указан ниже.
class ProcessInfo
{
public:
ProcessInfo()
: pid(-1), parentPid(0), commandLine(L""), name(L""), owner(L""), residentBytes(0), totalBytes(0), systemMillis(0), userMillis(0),
arch("")
{
childProcesses.resize(0);
};
~ProcessInfo() = default;
public:
int pid;
int parentPid;
std::vector childProcesses;
std::wstring commandLine;
std::wstring name;
std::wstring owner;
long residentBytes;
long totalBytes;
long systemMillis;
long userMillis;
std::string arch;
};
и часть типа ProcessInfoDTO выглядит следующим образом:
public class ProcessInfoDTO {
private static final long serialVersionUID = -212324578578245L;
private int pid;
private int parentPid;
private String commandLine;
private String name;
private String owner;
private int[] childProcesses;
private long residentBytes;
private long totalBytes;
private long systemMillis;
private long userMillis;
private SystemArch arch;
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
// Some more function definitions
// Some more function definitions
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... th-java-21
JNI CallStaticObjectMethod вызывает сбой в Java 21 ⇐ JAVA
Программисты JAVA общаются здесь
-
Anonymous
1721974829
Anonymous
Компания, в которой я работаю, недавно перешла на Java 21 с Java 8, что также обновило версию JNI, которая используется для совместимости с C++. Все функции (написанные на C++), вызываемые через JNI, нормально работают на Java 8, но
функция CallStaticObjectMethod выдает исключение Access Violation и вызывает сбой.
Это используется для вызова статического метода на стороне Java.
Функция, вызывающая CallStaticObjectMethod, выглядит следующим образом:
jobject Bindings::ToSystemArchObj(JNIEnv* env, const std::string& arch)
{
if (env == nullptr || arch == ARCH_UNSUPPORTED)
{
return nullptr;
}
jobject jstr = env->NewStringUTF(arch.c_str()); // I have tried converting the type of jstr from jobject to jstring
processArchObj = env->CallStaticObjectMethod(JniProcessInfoDTO::SystemArchClass, JniProcessInfoDTO::ofMethodId, jstr); // THIS LINE IS THROWING access violation and causing crash
return processArchObj;
}
Аргументы JniProcessInfoDTO::SystemArchClass и JniProcessInfoDTO::ofMethodId для этой функции инициализируются в отдельной функции, которая приведена ниже:
void JniProcessInfoDTO::initClass(JNIEnv* env)
{
jclass const localProcessInfoDTO = env->FindClass(JavaTypes::ProcessInfoDTO.c_str());
ProcessInfoDTORef = reinterpret_cast(env->NewGlobalRef(localProcessInfoDTO));
initFieldIDs(env);
// std::string const SystemArch = "Lcom/company/mfw/model/dto/SystemArch;";
SystemArchClass = env->FindClass(JavaTypes::SystemArch.c_str());
// (Ljava/lang/String;)Lcom/company/mfw/model/dto/SystemArch;
const std::string ofSign = "(" + JavaTypes::String + ")" + JavaTypes::SystemArch; //// std::string const String = "java/lang/String;";
ofMethodId = env->GetStaticMethodID(SystemArchClass, "of", ofSign.c_str());
}
Статическая функция do на стороне Java, которую предполагается вызывать, выглядит следующим образом:
package com.company.mfw.model.dto;
public enum SystemArch {
X86, X86_64, UNSUPPORTED;
public static SystemArch of(String arch) {
try {
return SystemArch.valueOf(arch);
} catch (Exception ignored) {
return UNSUPPORTED;
}
}
}
JNI загружается и выгружается следующим образом:
extern "C"
{
// cppcheck-suppress unusedFunction
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*)
{
// This is an entry point for initialization of Java classes.
// All required Java classes must exist and must be initialized here.
// JNI_OnLoad must not be wrapped with Safe Environment.
// JVM should be crashed in case of exceptions here.
JniGlobals::JVMConnector::InitJavaVM(vm);
JavaVMAttachArgs args;
args.version = JNI_VERSION_21;
args.name = nullptr;
args.group = nullptr;
JNIEnv* env = nullptr;
vm->AttachCurrentThread((void**)&env, &args);
JniContext::Current().JniEnv = env;
JniGlobals::unmaskFPSR();
GdiplusStartup(&JniGlobals::gdiplusToken, &JniGlobals::gdiplusStartupInput, nullptr);
Bindings::JniComponentDTO::initClass(env);
Bindings::JniWindowDTO::initClass(env);
Bindings::JniPointDTO::initClass(env);
Bindings::JniDimensionDTO::initClass(env);
Bindings::JniRectangleDTO::initClass(env);
Bindings::JniProcessInfoDTO::initClass(env);
Bindings::JniProcessStartupInfoDTO::initClass(env);
Bindings::JniProcessEndInfoDTO::initClass(env);
Bindings::JniKeyDTO::initClass(env);
Bindings::JniNativeMouseEvent::initClass(env);
Bindings::JniNativeKeyEvent::initClass(env);
Bindings::JniHooksSettings::initClass(env);
Bindings::WinSessionDTO::initClass(env);
JniGlobals::TimeManager::GetInstance().InitJavaHandlers(env);
JniGlobals::JavaObjectFactory::JavaObjectFactoryClass = env->FindClass("com/company/mfw/bridge/internal/JavaObjectsFactory");
JniGlobals::JavaObjectFactory::NewStringMethodID
= env->GetStaticMethodID(JniGlobals::JavaObjectFactory::JavaObjectFactoryClass, "newString", "([B)Ljava/lang/String;");
Log::GetInstance().Init();
LOG_TRACE(L"BEGIN");
auto osInfo = JniGlobals::WindowsSystemInfo::GetInstance().ReadOsInfo();
std::string csd(osInfo.szCSDVersion);
LOG_INFO(L"System info. Version: {}.{}, Build: {}, Platform ID: {}, CSD Version: {}", (int)osInfo.dwMajorVersion,
(int)osInfo.dwMinorVersion, (int)osInfo.dwBuildNumber, (int)osInfo.dwPlatformId,
csd.length() > 0 ? StringsConverter::StringToWstring(csd) : L"");
return JNI_VERSION_21;
}
// cppcheck-suppress unusedFunction
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM*, void*)
{
LOG_TRACE(L"BEGIN");
Gdiplus::GdiplusShutdown(JniGlobals::gdiplusToken);
JNIEnv* env = JniContext::Current().JniEnv;
Bindings::JniComponentDTO::releaseClass(env);
Bindings::JniWindowDTO::releaseClass(env);
Bindings::JniPointDTO::releaseClass(env);
Bindings::JniDimensionDTO::releaseClass(env);
Bindings::JniRectangleDTO::releaseClass(env);
Bindings::JniProcessInfoDTO::releaseClass(env);
Bindings::JniProcessStartupInfoDTO::releaseClass(env);
Bindings::JniProcessEndInfoDTO::releaseClass(env);
Bindings::JniKeyDTO::releaseClass(env);
Bindings::JniNativeMouseEvent::releaseClass(env);
Bindings::JniNativeKeyEvent::releaseClass(env);
Bindings::JniHooksSettings::releaseClass(env);
Bindings::WinSessionDTO::releaseClass(env);
}
} // extern "C"
Документация JNI не содержит никакой информации об этой функции. Может ли кто-нибудь мне здесь помочь?
[b]ОБНОВЛЕНИЕ 1: Все остальные методы JNI работают нормально, только этот вызывает сбой[/b]
[b]ОБНОВЛЕНИЕ 2[/b] Все эти функции вызываются для преобразования типа объекта C++ в тип Java. Метод Bindings::ToSystemArchObj вызывается методом, который выполняет это преобразование типа здесь:
/**
* Converts a ProcessInfoPtr to a Java ProcessInfoDTO object.
*
* @param env The JNI environment pointer.
* @param pi The ProcessInfoPtr object.
* @return The corresponding Java ProcessInfoDTO object or nullptr if the environment or ProcessInfoPtr is null.
*/
jobject Bindings::ToJavaType(JNIEnv* env, ProcessInfoPtr pi)
{
if (env == nullptr || pi == nullptr)
{
return nullptr; // Return nullptr if environment or ProcessInfoPtr is null
}
jobject joProcessInfoDTO = env->AllocObject(JniProcessInfoDTO::ProcessInfoDTORef); // Allocate a new ProcessInfoDTO object
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processPidFieldId, pi->pid); // Set process PID field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processParentPidFieldId, pi->parentPid); // Set process parent PID field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processChildProcessFieldId, ToJavaType(env, pi->childProcesses)); // Set child processes field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processCommandLineFieldId, ToJavaType(env, pi->commandLine)); // Set command line field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processNameFieldId, ToJavaType(env, pi->name)); // Set process name field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processOwnerFieldId, ToJavaType(env, pi->owner)); // Set process owner field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processResidentBytesFieldId, pi->residentBytes); // Set resident bytes field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processTotalBytesFieldId, pi->totalBytes); // Set total bytes field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processSystemMillsFieldId, pi->systemMillis); // Set system milliseconds field
env->SetIntField(joProcessInfoDTO, JniProcessInfoDTO::processUserMillsFieldId, pi->userMillis); // Set user milliseconds field
env->SetObjectField(joProcessInfoDTO, JniProcessInfoDTO::processArchFieldId, ToSystemArchObj(env, pi->arch)); // Set process architecture field
return joProcessInfoDTO; // Return the ProcessInfoDTO object
}
Приведенная выше функция пытается преобразовать ProcessInfo в объект Java ProcessInfoDTO. Тип ProcessInfo указан ниже.
class ProcessInfo
{
public:
ProcessInfo()
: pid(-1), parentPid(0), commandLine(L""), name(L""), owner(L""), residentBytes(0), totalBytes(0), systemMillis(0), userMillis(0),
arch("")
{
childProcesses.resize(0);
};
~ProcessInfo() = default;
public:
int pid;
int parentPid;
std::vector childProcesses;
std::wstring commandLine;
std::wstring name;
std::wstring owner;
long residentBytes;
long totalBytes;
long systemMillis;
long userMillis;
std::string arch;
};
и часть типа ProcessInfoDTO выглядит следующим образом:
public class ProcessInfoDTO {
private static final long serialVersionUID = -212324578578245L;
private int pid;
private int parentPid;
private String commandLine;
private String name;
private String owner;
private int[] childProcesses;
private long residentBytes;
private long totalBytes;
private long systemMillis;
private long userMillis;
private SystemArch arch;
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
// Some more function definitions
// Some more function definitions
}
Подробнее здесь: [url]https://stackoverflow.com/questions/78778717/jni-callstaticobjectmethod-is-causing-crash-with-java-21[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия