zcbdandan 2024-07-21 11:06 采纳率: 25%
浏览 89
已结题

JNA调用DLL报堆栈溢出错误(0xC00000FD)

问题描述:

我使用JNA调用一个第三方dll(必须要用,且自己无法修改,对方也不给修改的那种)时,该dll中其他方法均正常调用,唯独调用某个固定方法时,JVM直接crash,出现0xC00000FD的错误,这个错误是stack overflow,而且必现!
在vs2017中用C调用该dll也会出现这种现象,不过如果把vs2017的属性-->连接器-->系统-->堆栈保留大小设置为大于16M,即可运行正常。所以猜测是dll的这个方法是有过深的递归或者过大的局部数组。

运行环境

64位jdk1.8;JNA版本是5.12;操作系统是64位 win10;其他硬件环境是10代i7、16G内存。

已尝试过的方案

jvm运行配置参数 Xms4G、Xmx8G,其他参数比如-Xcheck:jni,Xss从128K--50M都试过,XX:StackShadowPages从3--50也都试过,均无法解决问题。
代码中使用“System.setProperty("jna.protected", "true")”,无法解决问题。
此外,jdk也试过11和13,JNA版本也用过目前最新的5.14,JNI方式也试过,均无法解决问题。
在C中起新线程调用那个有问题的方法——不能解决问题。
Java中起新线程指定stacksize为500M——不能解决问题。

2024年7月28日 结题了!

没有回答能解决问题,手动结题不返还悬赏,应该会每个回答者都分点儿吧?
这次提问咋说呢,回答里780%都是“参照GPT”啥的,每5条建议里会有34条我在提问里明确说过尝试过、没用的建议。

  • 写回答

33条回答 默认 最新

  • 杨同学* 2024-07-21 15:57
    关注
    获得0.15元问题酬金

    该回答结合ChatGPT4o及杨同学*共同作答, 如有帮助,还请采纳。
    你遇到的问题确实与堆栈大小有关,JNA和JVM的堆栈设置可能无法完全解决这个问题,特别是当第三方DLL有深度递归或大型局部数组时。既然在VS2017中增加堆栈大小可以解决问题,可以考虑以下方法:

    1. JNI Wrapper:创建一个C/C++的JNI Wrapper,通过该Wrapper设置更大的堆栈大小,然后从JNA调用这个JNI Wrapper函数。

    2. 独立进程调用:使用一个独立的进程调用这个DLL函数。你可以通过Java的ProcessBuilderRuntime.exec()来实现,并通过进程间通信(如管道、文件、网络)传递数据。

    示例:JNI Wrapper

    假设DLL函数为void problematic_function();,下面是一个简单的JNI Wrapper示例:

    C/C++代码:

    #include <jni.h>
    #include <windows.h>
    
    extern "C" {
        void problematic_function(); // 声明外部DLL函数
    }
    
    void __stdcall CallProblematicFunction() {
        problematic_function();
    }
    
    JNIEXPORT void JNICALL Java_MyClass_callProblematicFunction(JNIEnv *, jobject) {
        // 创建新线程并设置堆栈大小
        HANDLE hThread = CreateThread(NULL, 16 * 1024 * 1024, (LPTHREAD_START_ROUTINE)CallProblematicFunction, NULL, 0, NULL);
        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);
    }
    

    Java代码:

    public class MyClass {
        static {
            System.loadLibrary("MyJNIWrapper");
        }
    
        private native void callProblematicFunction();
    
        public void invokeProblematicFunction() {
            callProblematicFunction();
        }
    }
    

    示例:独立进程调用

    Java代码:

    import java.io.*;
    
    public class MyClass {
        public void invokeProblematicFunction() {
            try {
                ProcessBuilder pb = new ProcessBuilder("path_to_your_executable");
                Process process = pb.start();
                // 处理进程的输出和输入
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
                process.waitFor();
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    

    通过这些方法,你可以有效地避免JVM和JNA的堆栈限制,解决调用第三方DLL函数时的堆栈溢出问题。

    评论

报告相同问题?

问题事件

  • 系统已结题 7月29日
  • 修改了问题 7月28日
  • 修改了问题 7月28日
  • 修改了问题 7月23日
  • 展开全部