使用JNI从Java调用C#方法时触发JRE致命错误,求排查
Let's break down what's going wrong here and fix it step by step. That 0xe0434352 error is a telltale sign of an unhandled .NET runtime exception bubbling up into the Java Virtual Machine (JVM), which causes the crash. Here's how to diagnose and resolve the issue:
1. First: Confirm Your C++ Project is a C++/CLI Project
This is critical—you can't call .NET code from a pure native C++ project. Check your project settings:
- Right-click your C++ project → Properties
- Go to Configuration Properties > General
- Ensure Common Language Runtime Support is set to
Common Language Runtime Support (/clr)(not "No Common Language Runtime Support")
If this was set to pure native, the #using directive for the .NET netmodule wouldn't work at all, leading to undefined behavior when you try to call the C# method.
2. Fix Memory Leaks and Safe String Marshalling
Your current code uses Marshal::StringToHGlobalAnsi but never frees the allocated memory. This not only leaks memory but can cause unexpected crashes over time. Also, we need to handle the string conversion safely:
Replace your Alternate Step 2 code with this:
JNIEXPORT jstring JNICALL Java_jniTester_JNITester_welcome(JNIEnv *env, jclass thisclass, jstring inJNIStr) { const char *inCStr = env->GetStringUTFChars(inJNIStr, NULL); if (NULL == inCStr) return NULL; jstring result = NULL; try { // Convert UTF-8 C string to .NET String correctly System::String^ dotNetInput = System::Text::Encoding::UTF8->GetString( reinterpret_cast<unsigned char*>(const_cast<char*>(inCStr)), strlen(inCStr) ); // Call the C# method System::String^ outStr = HelloWorldJNI::HelloWorldJNI::Welcome(dotNetInput); // Convert .NET String to JNI jstring safely System::IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(outStr); char* converted = static_cast<char*>(ptr.ToPointer()); result = env->NewStringUTF(converted); // Free the allocated memory immediately System::Runtime::InteropServices::Marshal::FreeHGlobal(ptr); } catch (System::Exception^ ex) { // Catch .NET exceptions and convert them to Java exceptions const char* errorMsg = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(ex->Message).ToPointer(); env->ThrowNew(env->FindClass("java/lang/RuntimeException"), errorMsg); System::Runtime::InteropServices::Marshal::FreeHGlobal(System::IntPtr(const_cast<char*>(errorMsg))); } env->ReleaseStringUTFChars(inJNIStr, inCStr); return result; }
Key improvements here:
- We wrap the .NET calls in a
try-catchblock to catch any .NET exceptions (like null references, invalid arguments) and convert them into Java exceptions. This will give you a clear error message instead of a fatal JVM crash. - We properly free the memory allocated by
Marshal::StringToHGlobalAnsiusingMarshal::FreeHGlobal. - We use UTF-8 encoding explicitly when converting the C string to a .NET
String^, which matches the encoding fromGetStringUTFChars.
3. Verify .NET Netmodule Path and Loading
Ensure the path to your HelloWorldJNI.netmodule is correct:
- If you're using an absolute path, double-check that it points to the correct build output (Debug/Release) of your C# project.
- A better practice is to copy the netmodule into the output directory of your C++ project (where the DLL is generated), then use a relative path in the
#usingdirective:#using "HelloWorldJNI.netmodule"
This avoids hardcoding absolute paths that might break when moving projects.
4. Check C# Method Accessibility and Signature
Double-check your C# class and method:
- The
Welcomemethod ispublic static—that's correct for calling from C++/CLI. - Ensure the method accepts a
stringparameter and returns astring(no typos in parameter names or return types).
What to Do Next
After applying these fixes, run your Java program again. If there's an issue with the C# method (like a null argument), you'll now get a Java RuntimeException with the exact .NET error message instead of a fatal crash. This will make it much easier to pinpoint any remaining issues.
内容的提问来源于stack exchange,提问作者Walter Taus

