The company I work for recently moved to Java 21 from Java 8, which updated the JNI version as well that is used with interoperatibility with C++. All the function (written in C++) called through JNI work fine on Java 8, but
the function CallStaticObjectMethod
is throwing Access Violation exception and causing crash.
This function is used to call a static method on Java side.
The function which invokes CallStaticObjectMethod
is as below:
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;
}
The JniProcessInfoDTO::SystemArchClass
and JniProcessInfoDTO::ofMethodId
argument for this function are being initialized in a separate function which is below:
void JniProcessInfoDTO::initClass(JNIEnv* env)
{
jclass const localProcessInfoDTO = env->FindClass(JavaTypes::ProcessInfoDTO.c_str());
ProcessInfoDTORef = reinterpret_cast<jclass>(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());
}
The Java side static function do
which is supposed to get called looks like below:
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;
}
}
}
The JNI is being loaded and unloaded in the following way:
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/workfusion/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"<empty>");
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"
The JNI documentation does not contain any information about this function. Can anyone help me here?