首页 > 解决方案 > 从 Java 应用程序调用 C# 库:由于 StackOverflowException 而终止进程

问题描述

我有一个简单的 C# 类库,我将它包装在一个 C++/CLI 类库中并将其加载到一个简单的 Java 控制台应用程序中。但是当我运行 Java 应用程序时,我收到以下错误:

Process is terminated due to StackOverflowException.

Process finished with exit code -1073741571 (0xC00000FD)

我的 C# 库有一个 Class1.cs 文件:

using System;

namespace CSharpClassLibrary1
{
  public class Class1
  {
    public Class1() { }

    public void Print()
    {
      Console.WriteLine("Hello World From C#!");
    }
  }
}

我的 C++/CLI 包装器有两个文件:HelloWorld.h 和 CppClassLibrary1.cpp。

你好世界.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
  /*
   * Class:     HelloWorld
   * Method:    print
   * Signature: ()V
   */
  JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv*, jobject);

#ifdef __cplusplus
}
#endif
#endif

我通过在我的 Java 应用程序中运行以下形式的命令得到它:javac -h <directory> -d <directory> <source files>.

CppClassLibrary1.cpp:

#include "pch.h"
#include "HelloWorld.h"

using namespace CSharpClassLibrary1;

JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv* env, jobject obj)
{
  Class1^ cls = gcnew Class1();
  cls->Print();
}

我添加了 CSharpClassLibrary1 作为对 C++/CLI 包装器的引用。

我添加到“包含目录”设置以下路径:

C:\Users\ns16\AppData\Local\JetBrains\Toolbox\apps\IDEA-C\ch-0\192.6817.14\jbr\include
C:\Users\ns16\AppData\Local\JetBrains\Toolbox\apps\IDEA-C\ch-0\192.6817.14\jbr\include\win32

我的 Java 应用程序有一个 HelloWorld.java 文件:

public class HelloWorld {

    public native void print();

    static {
        try {
            System.loadLibrary("CppClassLibrary1");
        } catch (UnsatisfiedLinkError e) {
            System.err.println("Native code library failed to load.\n" + e);
        }
    }

    public static void main(String[] args) {
        HelloWorld hw = new HelloWorld();
        hw.print();
    }
}

我在 java.library.path 变量中指定了 CppClassLibrary1 库路径。

请帮我!我究竟做错了什么?

更新。对该问题的研究表明:

  1. 在 Java 应用程序中出现错误的hw.print();行。如果您将其注释掉,应用程序将成功启动。

  2. 如果在 CppClassLibrary1.cpp 文件中的 C++/CLI 包装器中将Java_HelloWorld_print函数主体替换为std::cout << "Hello World From C++/CLI!";行,Java 应用程序将成功启动并打印Hello World From C++/CLI!字符串。

  3. 如果您创建 C# 控制台应用程序,将 C# 库作为引用添加到其中,并将代码添加到Main方法中Class1 cls = new Class1(); cls.print();,应用程序将成功启动并打印Hello World From C#!字符串。

标签: javac#java-native-interfacec++-cli

解决方案


我将 C# 库程序集复制到带有 java.exe 文件的目录中(在我的系统中它位于C:\Users\ns16\AppData\Local\JetBrains\Toolbox\apps\IDEA-C\ch-0\192.6817.14\jbr\bin),现在 Java 应用程序可以工作了!我不想将程序集移出项目目录,但这是我找到的唯一解决方案。


推荐阅读