JNI CallStaticObjectMethod вызывает сбой в Java 21JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 JNI CallStaticObjectMethod вызывает сбой в Java 21

Сообщение 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 не содержит никакой информации об этой функции. Может ли кто-нибудь мне здесь помочь?
ОБНОВЛЕНИЕ 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»